Introduction
In recent decades, Philadelphia has experienced substantial changes
in population dynamics, economic fluctuations, and redevelopment
pressures. Among these changes, housing values have become a key
indicator of the socio-economic conditions within the city’s
neighborhoods. Rising housing values typically reflect a higher presence
of wealthier residents or a neighborhood undergoing gentrification,
while declining housing values often signal increased economic pressure
or decline. Therefore, accurately forecasting the median housing values
across Philadelphia is crucial for urban planners and policymakers,
helping them to proactively address potential risks such as displacement
and disinvestment. Supporting Philadelphia’s long-term vision of
fostering vibrant, diverse, and resilient communities is also
essential.
To better understand the potential factors influencing housing values
in Philadelphia, we identify several key variables: educational
attainment, vacancy rates, the proportion of single-family homes, and
poverty levels. These factors are closely related to housing market
trends and provide insights into the neighborhood’s socio-economic
status.
Educational attainment is closely linked to the socio-economic
characteristics of neighborhoods. Individuals with higher educational
attainment typically earn higher incomes and contribute more to local
economies. A higher concentration of individuals with advanced
educational backgrounds tends to increase the demand for well-designed
housing in affluent neighborhoods. With a consistent supply, housing
prices and values are likely to rise. Similarly, a high poverty rate
also indicates a declining community. Since many residents cannot afford
luxury housing, the housing values in those neighborhoods are likely to
be Lower.
High vacancy rates often correlate with declining neighborhoods and
reduced median house values. Research shows that vacant properties
affect multiple facets of community life, such as housing and
neighborhood vitality, crime prevention efforts, and the well-being of
commercial districts. As a result, areas with numerous vacant housing
units typically see diminished median housing values.
The proportion of single-family homes in an area influences housing
values. These homes are generally private and comfortable, making them
more desirable in many U.S. housing markets. However, they are
relatively common in suburban neighborhoods and may suffer from low
accessibility and limited infrastructure, which can negatively affect
their property values as well.
In this study, we utilize ordinary least squares (OLS) regression to
analyze the relationship between these socioeconomic factors and median
house values in Philadelphia. By examining these relationships, we aim
to identify critical predictors of median housing values throughout
Philadelphia and offer insights for decision-makers and community
initiatives.
Methods
Data Cleaning
To predict median house values in Philadelphia, we obtained the
original dataset from the United States Census data. The dataset
represents census block groups from the year 2000 and initially
contained 1,816 observations. The key variables included:
- POLY_ID – Census Block Group ID
- MEDHVAL – Median value of all owner-occupied
housing units
- PCBACHMORE – Proportion of residents in the block
group with at least a bachelor’s degree
- PCTVACANT – Proportion of housing units that are
vacant
- PCTSINGLES – Percentage of housing units that are
detached single-family houses
- NBELPOV100 – Number of households with incomes
below 100% of the poverty level
- MEDHHINC – Median household income
To refine the dataset for modeling purposes, we applied the following
filtering criteria:
- Retained block groups with a population greater than 40
- Included only block groups that contained housing units
- Excluded records where the median house value was below $10,000
Additionally, we removed a specific block group in North Philadelphia
that exhibited inconsistencies, with an unusually high median house
value (over $800,000) despite a very low median household income (less
than $8,000).
After data cleaning, the final dataset contained 1,720
observations.
Exploratory Data Anaylsis
Summary Statistics
We will first examine the summary statistics ( mean
and standard deviation (SD)) of key variables in the
dataset, including the dependent variables MEDHVAL (Median
House Value), and predictors NBELPOV100 (Households Living in
Poverty), PCTBACHMOR (% of Individuals with Bachelor’s Degrees
or Higher), PCTVACANT(% of Vacant Houses), PCTSINGLES(
% of Single House Units).
The mean (\(\bar{X}\)) represents the average value of
a variable and is calculated as:
\[
\bar{X} = \frac{1}{n} \sum_{i=1}^{n} X_i
\]
where:
- \(X_i\) represents each individual
observation
- \(n\) is the total number of
observations
The mean gives us a single representative value of the dataset. To
measure variability, we use the standard deviation
(SD), which quantifies how much the values in a dataset deviate
from the mean. The formula for the sample standard deviation (\(s\)) is:
\[
s = \sqrt{\frac{1}{n-1} \sum_{i=1}^{n} \left( X_i - \bar{X} \right)^2}
\]
where:
- \(X_i\) represents each individual
observation
- \(\bar{X}\) is the mean of the
observations
- \(n\) is the total number of
observations
A larger standard deviation indicates that the data points are more
spread out, while a smaller standard deviation suggests that the data
points are closer to the mean.
Distributions
We will also examine the histograms and apply log transformations for
key variables to assess whether the transformed variables follow a more
normal-like distribution.
Histograms provide a visual representation of how a
variable’s values are distributed, helping to identify whether the data
follows a normal distribution, is
right-skewed, or left-skewed. Linear
regression model assume that variables are approximately normally
distributed.
X-axis: The values of the variable (e.g., house
prices, income levels).
Y-axis: The frequency of observations within
each bin.
If the histogram is right-skewed, it suggests that a
small number of observations have significantly higher values compared
to the rest. For variables following a right-skewed
distribution, we will apply a log
transformation to these variables to improve normality. Since
the log transformation is undefined for zero or
negative values, we must first check whether any variable contains
zero.
- If no zeros presents, we apply the standard log
transformation:
\[
X' = \log_{10} (X)
\]
- If zeros present, we adjust by adding 1 before
taking the log:
\[
X' = \log_{10} (X + 1)
\]
This ensures that all values remain positive and avoids undefined
values.
By comparing the original histograms with the
log-transformed histograms, we will assess whether the
transformation improves the suitability of the data for predictive
modeling.
Correlations
We will analyze correlations between predictors, to
detect potential multicollinearity before proceeding
with regression analysis, which can distort model interpretations.
Multicollinearity occurs when predictors are highly correlated, which
can lead to unstable regression coefficients. It also inflates standard
errors, reducing the statistical significance of predictors, and
increases the risk of overfitting, as redundant variables do not
contribute new information to the model.
The correlation coefficient \(r\) is calculated as:
\[
r = \frac{\sum_{i=1}^{n} (x_i - \bar{x})(y_i -
\bar{y})}{\sqrt{\sum_{i=1}^{n} (x_i - \bar{x})^2 \sum_{i=1}^{n} (y_i -
\bar{y})^2}}
\] In a more concise way, this above formula is also equivalent
to the following:
\[
r = \frac{1}{n-1} \sum_{i=1}^{n} \left( \frac{x_i - \bar{x}}{S_x}
\right) \left( \frac{y_i - \bar{y}}{S_y} \right)
\] where:
- \(X_i\) and \(Y_i\) are individual data points for
variables \(X\) and \(Y\), respectively.
- \(\bar{X}\) and \(\bar{Y}\) are the mean
values of \(X\) and \(Y\).
- The numerator represents the covariance between \(X\) and \(Y\), while the denominator
normalizes the values.
The correlation coefficient \(r\)
ranges from -1 to 1: A value of +1 indicates a perfect
positive linear relationship, while a value of -1 indicates a perfect
negative linear relationship. A value of 0 suggests no linear
relationship between the variables, meaning changes in one do not
influence the other.
Multiple Regression
After getting a general sense of the data, we conduct multiple
regression analysis to examine the relationship between the dependent
variable, Median House Value (MEDHVAL), and the
predictors, education attainment (PCTBACHMOR),
number of Households Living in Poverty (NBELPOV100),
percentage of Vacant Houses (PCTVACANT), and
percentage of Single House Units (PCTSINGLES).
Regression analysis is a statistical method to examine the relationship
between a dependent variable and one or more predictors. With this type
of analysis, researchers can identify the strength and direction of the
relationship between variables, make predictions, and assess the
significance of predictors. The model also estimates coefficients for
each predictor, which represent the expected change in the dependent
variable for a one-unit change in the predictor, holding other
predictors constant. For this study, the multiple regression model is
formulated as follows: \[
\text{LNMEDHVAL} = \beta_0 + \beta_1 \text{PCTVACANT} + \beta_2
\text{PCTSINGLES} + \beta_3 \text{PCTBACHMOR} + \beta_4
\text{log(NBELPOV100)} + \epsilon
\] where LNMEDHVAL is the log-transformed median
house value, PCTVACANT is the proportion of vacant
housing units , PCTSINGLES is the proportion of the
single family housing , PCTBACHMOR is the percentage of
the residents holding bachelor’s degree or higher, and
log(NBELPOV100) is the log-transformed number of
households living below the poverty line.
\(\beta_0\) is the intercept, \(\beta_1\), \(\beta_2\), \(\beta_3\), and \(\beta_4\) are the coefficients for each
predictor, and \(\epsilon\) is the
error term. The coefficient \(\beta_1\), \(\beta_2\), \(\beta_3\), \(\beta_4\) represent the change in the
log-transformed median house value for a one-unit change in the
corresponding predictor, holding other predictors constant. The error
term \(\epsilon\) accounts for the
variability in the dependent variable that is not explained by the
predictors.
Regression Assumptions
There are several assumptions associated with regression analysis
that need to be met for the results to be valid. These assumptions
including linearity, independence of
observations, homoscedasticity,
normality of residuals, no
multicollinearity, and no fewer than 10 observations
per predictors.
First, Linearity assumes that the relationship
between the dependent variable and the predictors is linear. To verify
this assumption, we made scatter plots of the dependent variable against
each predictor. If the relationship appears to be linear, the
assumptions was met.
Second, Independence of Observations assumes that
the observations are independent of each other. There should be no
spatial or temporal or other forms of dependence in the data.
Third, Homoscedasticity assumes that the variance of
the residuals \(\epsilon\) is constant
regardless of the values of each level of the predictors. To check this
assumption, we made a scatter plot of the standardized residuals against
the predicted values. If the residuals are evenly spread around zero,
the assumption was met. Any patterns may indicate the presence of
heteroscedasticity.
Fourth, Normality of Residuals assumes that the
residuals are normally distributed. We examined the histogram of the
standardized residuals to check if they are approximately normally
distributed. If the histogram is bell-shaped, the assumption was
met.
Fifth, No Multicollinearity assumes that the
predictors are not highly correlated with each other. We calculated the
correlation matrix of the predictors to check for multicollinearity. If
the correlation coefficients are is not greater than 0.8 or less than
-0.8, the assumption was met.
Finally, No Fewer than 10 Observations per Predictor
assumes that there are at least 10 observations for each predictor in
the model. Since there are over 1,700 observations in the dataset, this
assumption was met.
Parameter Estimations
After verifing the assumptions of the regression, we start the
regression analysis. Several parameters need to estimate here: - \(\beta_0\), which is the intercept - \(\beta_1, \dots, \beta_k\), which are
coefficients of each independent variables - \(\sigma^2\), the variance of the error
terms, which represents the variability in the dependent variable that
is not explained by the predictors.
The least squares method estimates the coefficients by minimizing
the sum of squared errors (SSE), which is the sum of
the squared differences between the observed values and the predicted
values. The formula for SSE is:
\[
\text{SSE} = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 = \sum_{i=1}^{n} (y_i -
\hat{\beta}_0 - \hat{\beta}_1 x_{i1} - \dots - \hat{\beta}_k x_{ik})^2
\] where \(y_i\) is the actual
or observed value, \(\hat{y}_i\) is the
predicted value, \(\hat{\beta}_0, \dots,
\hat{\beta}_k\) are the estimated coefficients, and \(x_{i1}, \dots, x_{ik}\) are the predictor
values for the \(i\)-th
observation.
With the Error Sum of Squares (SSE) calculated, we can estimate the
variance of the error terms \(\sigma^2\) using the formula:
\[
\sigma^2 = \frac{\text{SSE}}{n - (k+1)}
\] where \(n\) is the number of
observations and \(k\) is the number of
predictors in the model.
Model Evaluation
We evaluated the model’s fitness using the coefficient of
determination \(R^2\) and the adjusted
\(R^2\). The coefficient of
determination \(R^2\) measures the
proportion of variance in the dependent variable that is explained by
the predictors. The adjusted \(R^2\)
adjusts the \(R^2\) value based on the
number of predictors, which help to provide a more accurate measure of
model fit for multiple regression, as the increase the number of
predictors can artificially inflate the \(R^2\) value.
To obtain \(R^2\), \(SST\) or the total sum of squares, needed
to be calculated first. The \(SST\)
measures the total variance in the dependent variable, given by: \[
SST = \sum_{i=1}^{n} (y_i - \bar{y})^2
\] Where \(y_i\) is the observed
value, and \(\bar{y}\) is the mean of
the observed value. Then, the \(R^2\)
can be obtained by: \[
R^2 = 1 - \frac{SSE}{SST}
\] After that, \(R^2\) is
adjusted as follows based on the number of observations \(n\) and the number of predictors \(k\): \[
R^2_{\text{adj}} = 1 - \frac{(1 - R^2)(n - 1)}{n - k - 1}
\]
Hypothesis Testing
In this analysis. several hypothesis tests are conducted to determine
the significance of the model and its predictors. The overall
significance of the model is assessed using the F-ratio. It compares the
variance explained by the model to the variance not explained by the
model.A higher F-ratio indicates that the model explains a significant
amount of variance in the dependent variable compared to the residual
variance.
The null hypothesis and alternative hypothesis for the F-ratio are
stated as follows:
The null hypothesis \(H_0\) states that all coefficients
are equal to zero, meaning that the predictors do not explain the
variance in the dependent variable (median house value). Stated as:
\[
H_0: \beta_1 = \beta_2 = \beta_3 = \beta_4 = 0
\]
The alternative hypothesis \(H_a\) states that at least one
coefficient is not equal to zero. In our case, this means that at least
one predictor explains the variance in the dependent variable (median
house value). Stated as: \[
H_a: \text{At least one } \beta_i \neq 0
\]
We also conduct a t-test to determine the significance of each
individual predictor in the model:
The null hypothesis \(H_{0i}\) states that the
coefficient for the predictor i is equal to zero, meaning that the
predictor does not explain the variance in the dependent variable
(median house value). Stated as:
\[
H_{0i}: \beta_i = 0
\]
The alternative hypothesis \(H_{ai}\) states that the
coefficient for the predictor i is not equal to zero, meaning that the
predictor explains the variance in the dependent variable (median house
value). Stated as:
\[
H_{ai}: \beta_i \neq 0
\]
Additional Analysis
Stepwise Regression
In addition to the multiple regression analysis, we conduct stepwise
regression analysis to identify the most significant predictors of
median house values in Philadelphia. Stepwise regression is a method
that automatically selects the best subset of predictors for the model.
It involves adding or removing predictors based on their statistical
significance (P-value) and the AIC (Akaike Information Criterion). The
stepwise regression analysis will help us identify the most important
predictors and improve the overall model fits.
However, there are several limitations to stepwise regression. First,
the final stepwise regression model is not guaranteed to be optimal in
any specific sense. There may be other models that are as good as, or
even better than the one selected by stepwise regression, but the
procedure only yeilds a single model. Second, the stepwise regression
does take into account researchers’ knowledge about the predictors.
Important variables may be exclude from the model if they are not
included in the initially. Moreover, This method also runs the risk of
Type I and Type II errors—meaning it may include unimportant variables
or exclude important ones.
Cross-Validation
To evaluate the performance of the regression model, we conduct
K-fold cross-validation. Cross-validation is a technique used to evluate
the performance of the predictive models. In K-fold Cross-Validation,
the dataset is randomly divided into K equal-sized folds. The model is
trained on K-1 folds and tested on the remaining fold. This process is
repeated K times, with each fold serving as the test set exactly once.
The average performance across all K folds is then calculated.
Cross-validation helps to assess the model’s generalization performance
and reduce the risk of overfitting.
In our analysis, we used K=5, which is a common choice for
cross-validation. The root mean squared error (RMSE) is used to compare
the performance of different models. The RMSE measures the difference
between the predicted values and the actual values. A lower value of
RMSE indicates a better predictive model.
The mean square errors is calculated as follows: \[
\text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2
\] And the root mean square errors (RMSE) is the square root of
the mean square errors (MSE): \[
\text{RMSE} = \sqrt{\text{MSE}}
\]
Software and Packages
In this analysis, we utilize the R programming language, a
professional statistical software widely used for data analysis and
visualization.The following libraries and packages have been employed to
conduct the analysis:
tidyverse: A collection of R packages for data
manipulation and visualization.
sf: A package for spatial data processing, especially
for handling shapefiles.
ggplot2: A popular visualization package for creating
high-quality map and charts, part of the tidyverse
collection.
ggcorrplot: A package designated to visualize
correlation matrices using ggplot2.
patchwork: A package for combining multiple ggplot2
plots into a single plot.
MASS: A package provides multiple functions and
datasets for statistical analysis, including linear models.
caret: A package for creating predictive models and
conducting machine learning tasks, used in cross-validation and k-fold
analysis.
kableExtra: A package for creating tables with advanced
formatting options.
Results
Exploratory Results
The table below presents the summary statistics for the key
variables, an overview of the central tendency and variability. The
dependent variable median house value has a mean of 66,287.73,
indicating that the average median house value by census tract in
Philadelphia is approximately 66,287.73 dollar. The standard deviation
of 60,006.08 dollar suggests that house values exhibit significant
variability across census tracts.
For the predictor variables, all have standard deviations close to or
greater than the mean, indicating large differences in educational
attainment, economic status, housing occupancy, and housing structure
composition across Philadelphia’s census block groups.
dependent_var <- "MEDHVAL"
predictors <- c("PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES")
summary_stats <- data %>%
dplyr::select(all_of(c(dependent_var, predictors))) %>%
summarise_all(list(Mean = mean, SD = sd), na.rm = TRUE) %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "Value") %>%
separate(Variable, into = c("Variable", "Stat"), sep = "_") %>%
pivot_wider(names_from = Stat, values_from = Value)
summary_stats$Variable <- recode(summary_stats$Variable,
"MEDHVAL" = "Median House Value",
"NBELPOV100" = "# Households Living in Poverty",
"PCTBACHMOR" = "% of Individuals with Bachelor’s Degrees or Higher",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
)
summary_stats <- summary_stats %>%
mutate(
Mean = round(Mean, 2),
SD = round(SD, 2)
)
summary_stats <- summary_stats %>%
arrange(Variable == "Median House Value")
predictor_rows <- which(summary_stats$Variable != "Median House Value")
dependent_rows <- which(summary_stats$Variable == "Median House Value")
# Determine the start and end rows for each group
start_pred <- min(predictor_rows)
end_pred <- max(predictor_rows)
start_dep <- min(dependent_rows)
end_dep <- max(dependent_rows)
# Create the table using kable and add extra formatting
kable(summary_stats, caption = "Summary Statistics",
align = c("l", "l", "l"), booktabs = TRUE, escape = FALSE ) %>%
add_header_above(c(" " = 1, "Statistics" = 2)) %>%
kable_styling(full_width = FALSE) %>%
group_rows("Predictors", start_pred, end_pred) %>%
group_rows("Dependent Variable", start_dep, end_dep)%>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = TRUE)
Summary Statistics
|
|
Statistics
|
|
Variable
|
Mean
|
SD
|
|
Predictors
|
|
% of Individuals with Bachelor’s Degrees or Higher
|
16.08
|
17.77
|
|
# Households Living in Poverty
|
189.77
|
164.32
|
|
% of Vacant Houses
|
11.29
|
9.63
|
|
% of Single House Units
|
9.23
|
13.25
|
|
Dependent Variable
|
|
Median House Value
|
66287.73
|
60006.08
|
Histogram Distribution
One of the assumptions of OLS regression is that variables follow a
normal distribution. To assess the distribution of key variables, their
histograms are presented below. As seen in the plots, all key variables
exhibit left-skewness, meaning their distributions are right-skewed
(positively skewed), with a concentration of smaller values and a long
right tail.
longer_version<- data %>%
pivot_longer(cols = c("MEDHVAL", "PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES"),
names_to = "Variable",
values_to = "Value")
ggplot(longer_version,aes(x = Value)) +
geom_histogram(aes(y = ..count..), fill = "black", alpha = 0.7) +
facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
"MEDHVAL" = "Median House Value",
"PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
"NBELPOV100" = "# Households Living in Poverty",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
))) +
labs(x = "Value", y = "Count", title = "Histograms of Dependent and Predictor Variables") +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

To meet the normality assumption of OLS, log transformation is
applied where necessary to improve distributional symmetry. This
transformation helps normalize the distributions, making them more
suitable for regression analysis. The histograms of the log-transformed
variables indicate a more normal-like distribution. However, some slight
skewness remains: the dependent variable (Log Median House
Value) and the predictor (Log % Single House Value) are
slightly left-skewed, while the predictors Log % Households in
Poverty and Log % Vacant Houses are slightly
right-skewed.
data <- data %>%
mutate(
LNMEDHVAL = log(MEDHVAL),
LNPCTBACHMOR = log(1+PCTBACHMOR),
LNNBELPOV100 = log(1+NBELPOV100),
LNPCTVACANT = log(1+PCTVACANT),
LNPCTSINGLES = log(1+PCTSINGLES)
)
longer_version2 <- data %>%
pivot_longer(cols = c(LNMEDHVAL, LNPCTBACHMOR ,LNNBELPOV100,LNPCTVACANT, LNPCTSINGLES),
names_to = "Variable",
values_to = "Value")
ggplot(longer_version2,aes(x = Value)) +
geom_histogram(aes(y = ..count..), fill = "red", alpha = 0.7) +
facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
"LNMEDHVAL" = "Log Median House Value",
"LNPCTBACHMOR" = "Log % with Bachelor’s Degree",
"LNNBELPOV100" = "Log # Households in Poverty",
"LNPCTVACANT" = "Log % Vacant Houses",
"LNPCTSINGLES" = "Log % Single House Units"
))) +
labs(x = "Value", y = "Count", title = "Histograms of Dependent and log transformed Predictor Variables") +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

Other regression assumptions will be assessed separately in the
Regression Assumption Checks section later.
Choropleth Maps
Linearity assumes that the relationship between the dependent
variable and the predictors is linear. To examine this relationship, we
analyze the spatial distribution of key variables. Certain predictor
maps exhibit patterns similar to the dependent variable, suggesting a
strong potential relationship.
Below is the choropleth map of the dependent variable, Log
Transformed Median House Value. It reveals that central city areas
and Germantown/Chestnut Hill have higher median house values, while
North Philadelphia has lower values.
ggplot(shape) +
geom_sf(aes(fill = LNMEDHVAL), color = "transparent") +
scale_fill_gradientn(colors = c("#fff0f3", "#a4133c"),
name = "LNMEDHVAL",
na.value = "transparent") +
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
labs(title = "Log Transformed Median House Value")

To understand the spatial relationship between the dependent variable
and predictors, we present four key predictor maps below as well.
shpe_longer<- shape %>%
pivot_longer(cols = c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV"),
names_to = "Variable",
values_to = "Value")
custom_titles <- c(
PCTVACANT = "Percent of Vacant Houses",
PCTSINGLES = "Percent of Single House Units",
PCTBACHMOR = "Percent of Bachelor's Degree or Higher",
LNNBELPOV = "Logged Transformed Poverty Rate"
)
plot_list <- lapply(unique(shpe_longer$Variable), function(var_name) {
data_subset <- subset(shpe_longer, Variable == var_name)
ggplot(data_subset) +
geom_sf(aes(fill = Value), color = "transparent") +
scale_fill_gradientn(
colors = c("#fff0f3", "#a4133c"),
name = var_name,
na.value = "transparent"
) +
labs(title = custom_titles[[var_name]]) +
theme(
legend.text = element_text(size = 8),
legend.title = element_text(size = 10),
legend.key.size = unit(0.3, "cm"),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 15, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)
)
})
# Combine the plots into a grid (2 columns by 2 rows)
combined_plot <- (plot_list[[1]] + plot_list[[2]]) /
(plot_list[[3]] + plot_list[[4]])
combined_plot

These maps also help identify whether predictors are closely related
to each other, which could cause multicollinearity problems. The
Percent of Bachelor’s Degree or Higher map looks very similar
to the Log Transformed Median House Value map, suggesting that
areas with more college graduates tend to have higher house values.
Also, the Percent of Vacant Houses and Percent of Single
House Units maps share a similar pattern—North Philadelphia and
University City have a high percentage of vacant houses and a low
percentage of single-house units, while Germantown/Chestnut Hill and Far
Northeast Philadelphia show the opposite trend. This suggests that these
two predictors may be strongly related, which could lead to
multicollinearity issues in the regression analysis.
Examining Multicollinearity & Correlation Matrix
To further examine multicollinearity, we create a correlation matrix
between predictors. All correlation values are below 0.7, indicating
that no severe multicollinearity occurs in our model.
Among them, % of Single House Units and
Logged Households Living in Poverty have a correlation
of -0.32, suggesting some relationship but not strong enough to cause
severe multicollinearity. Looking back at the choropleth maps of these
two predictors, their spatial patterns are not similar. % of
Single House Units and % of Individuals with a
Bachelor’s Degree or Higher have a correlation of -0.3, again
indicating some relationship without severe multicollinearity. The
choropleth maps of these two predictors also do not exhibit similar
spatial patterns. Additionally, while the choropleth maps of
Percent of Vacant Houses and Percent of Single
House Units share a similar pattern, as mentioned before, their
correlation value is only 0.2, suggesting a weak relationship without
multicollinearity.
There is no severe multicollinearity among the predictors, supporting
the assumptions of OLS regression. However, if the correlation matrix
had shown high correlations (\(|r| \)), we could further confirm the
severity of multicollinearity using the Variance Inflation
Factor (VIF) (VIF < 5 indicates low
multicollinearity and is generally acceptable, while VIF \(\geq\) 5 suggests moderate to high
multicollinearity that may require attention. If VIF \(\geq\) 10, severe
multicollinearity is present, necessitating corrective measures).
custom_labels <- c(
"% of Individuals with Bachelor’s Degrees or Higher" = "PCTBACHMOR",
"% of Vacant Houses" = "PCTVACANT",
"% of Single House Units" = "PCTSINGLES",
"# Households Living in Poverty" = "LNNBELPOV100"
)
predictor_vars <- data[, c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV100")]
cor_matrix <- cor(predictor_vars, use = "complete.obs", method = "pearson")
print(cor_matrix)
## PCTVACANT PCTSINGLES PCTBACHMOR LNNBELPOV100
## PCTVACANT 1.0000000 -0.1513734 -0.2983580 0.2495470
## PCTSINGLES -0.1513734 1.0000000 0.1975461 -0.2905159
## PCTBACHMOR -0.2983580 0.1975461 1.0000000 -0.3197668
## LNNBELPOV100 0.2495470 -0.2905159 -0.3197668 1.0000000
rownames(cor_matrix) <- names(custom_labels)
colnames(cor_matrix) <- names(custom_labels)
ggcorrplot(cor_matrix,
method = "square",
type = "lower",
lab = TRUE,
lab_size = 3,
colors = c("#d73027", "white", "#1a9850"))+
labs(title = "Correlation Matrix for all Predictor Variables") +
theme(plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x = element_text(size = 7),
axis.text.y = element_text(size = 7),
axis.title = element_text(size = 8))

Regression Results
Parameter Estimations
Four independent variables were included in the multiple regression
model to predict the log-transformed median house value
(LNMEDHVAL) in Philadelphia at census block group level,
including the proportion of vacant housing units
(PCTVACANT), the proportion of single-family housing units
(PCTSINGLES), the proportion of residents with a bachelor’s
degree or higher (PCTBACHMOR), and the number of households
living below the poverty line (LNNBELPOV100). The
regression results are presented below:
fit <- lm(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=data)
summary(fit)
##
## Call:
## lm(formula = LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR +
## LNNBELPOV100, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.25825 -0.20391 0.03822 0.21744 2.24347
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 11.1137661 0.0465330 238.836 < 2e-16 ***
## PCTVACANT -0.0191569 0.0009779 -19.590 < 2e-16 ***
## PCTSINGLES 0.0029769 0.0007032 4.234 2.42e-05 ***
## PCTBACHMOR 0.0209098 0.0005432 38.494 < 2e-16 ***
## LNNBELPOV100 -0.0789054 0.0084569 -9.330 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3665 on 1715 degrees of freedom
## Multiple R-squared: 0.6623, Adjusted R-squared: 0.6615
## F-statistic: 840.9 on 4 and 1715 DF, p-value: < 2.2e-16
The regression output tells us that the median housing values are
highly significant correlated with the proportion of vacant housing
units(PCTVANT), the proportion of single-family housing
units(PCTSINGLES), the proportion of residents with a
bachelor’s degree or higher (PCTBACHMOR), and the
log-transformed number of households living below the poverty line
(LNNBELPOV), with \(p-value<0.0001\) for all four
predictors.
As the proportions of vacant housing units (PCTVANT)
goes up by 1 unit (1%), the median house value goes down by
approximately 1.915%, with holding all other three predictors constant.
In addition, the respective \(p-value\)
for \(\beta_1\) is less than 0.0001,
indicating that if there is no relationship between PCTVANT
and the dependent variable (i.e., if the null hypothesis that \(\beta_1 = 0\) is true), then the
probability of getting a \(\beta_1\)
coefficient estimate of -0.0191569 is less than 0.0001. We can safely
reject the null hypothesis \(H_0: \beta_1 =
0\) for \(H_a: \beta_1 \neq
0\).
\[(e^{\beta} - 1) \times 100\% =
(e^{-0.0191569} - 1) \times 100\% \approx -1.915\% \]
Similarly, as the proportion of single-family housing units
(PCTSINGLES) goes up by 1 unit (1%), the median house value
goes up by approximately 0.298%, with holding all other three predictors
constant. The \(p-value\) for \(\beta_2\) is less than 0.0001, indicating
that if there is no relationship between PCTSINGLES and the
dependent variable (i.e., if the null hypothesis that \(\beta_2 = 0\) is true), then the
probability of getting a \(\beta_2\)
coefficient estimate of 0.0029769 is less than 0.0001. We can also
safely reject the null hypothesis \(H_0:
\beta_2 = 0\) for \(H_a: \beta_2 \neq
0\).
\[(e^{\beta} - 1) \times 100\% =
(e^{-0.0029769} - 1) \times 100\% \approx 0.298\% \]
Furthermore, as the proportion of residents with a bachelor’s degree
or higher (PCTBACHMOR) goes up by 1 unit (1%), the median
house value goes up by approximately 2.09%, with holding all other three
predictors constant. Similar to \(\beta_2\), the \(p-value\) for \(\beta_3\) is less than 0.0001, indicating
that if there is no relationship between PCTBACHMOR and the
dependent variable (i.e., if the null hypothesis that \(\beta_3 = 0\) is true, then the probability
of getting a \(\beta_3\) coefficient
estimate of 0.0209098 is less than 0.0001. We can also safely reject the
null hypothesis \(H_0: \beta_3 = 0\)
for \(H_a: \beta_3 \neq 0\).
\[(e^{\beta} - 1) \times 100\% =
(e^{0.0209098} - 1) \times 100\% \approx 2.09\% \]
Lastly, as 1 percent increase in the number of households living
below the poverty line, the median house value goes down by
approximately 0.078% , with holding all other three predictors constant.
The \(p-value\) for \(\beta_4\) is also less than 0.0001
indicating that if there is no relationship between number of households
below poverty line and the dependent variable (i.e., if the null
hypothesis that \(\beta_4 = 0\) is
true), then the probability of getting a \(\beta_4\) coefficient estimate of
-0.0789054 is less than 0.0001. As stated before, we can also safely
reject the null hypothesis \(H_0: \beta_4 =
0\) for \(H_a: \beta_4 \neq
0\).
\[(1.01^{\beta} - 1) \times 100\% =
(1.01^{-0.0789054} - 1) \times 100\% \approx -0.078\%\]
Model Fit
fit <- lm(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=data)
summary(fit)
##
## Call:
## lm(formula = LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR +
## LNNBELPOV100, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.25825 -0.20391 0.03822 0.21744 2.24347
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 11.1137661 0.0465330 238.836 < 2e-16 ***
## PCTVACANT -0.0191569 0.0009779 -19.590 < 2e-16 ***
## PCTSINGLES 0.0029769 0.0007032 4.234 2.42e-05 ***
## PCTBACHMOR 0.0209098 0.0005432 38.494 < 2e-16 ***
## LNNBELPOV100 -0.0789054 0.0084569 -9.330 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3665 on 1715 degrees of freedom
## Multiple R-squared: 0.6623, Adjusted R-squared: 0.6615
## F-statistic: 840.9 on 4 and 1715 DF, p-value: < 2.2e-16
First, the residuals from the model show a reasonable distribution of
errors, with a median residual of 0.03822, a minimum value of -2.26, a
first quartile of -0.20, and a third quartile of 0.22, and a maximum
value of 2.24. This distribution shows that the model captures the
variability in the dependent variable well (logged transformed median
home value), although some of the residuals are larger than 2.5 standard
deviations from the mean, which are the outliers.
Moreover, the model has a multiple \(R^2\) value of 0.6623 and an adjusted \(R^2\) value of 0.6615, indicating that
approximately 66% of the variance in LNMEDHVAL is explained
by the predictors. The \(F-statistic\)
of 840.0 with a \(p-value\) less than
0.0001, indicating that the model is statistically significant.
anova_table <- anova(fit)
anova_table
## Analysis of Variance Table
##
## Response: LNMEDHVAL
## Df Sum Sq Mean Sq F value Pr(>F)
## PCTVACANT 1 180.392 180.392 1343.087 < 2.2e-16 ***
## PCTSINGLES 1 24.543 24.543 182.734 < 2.2e-16 ***
## PCTBACHMOR 1 235.118 235.118 1750.551 < 2.2e-16 ***
## LNNBELPOV100 1 11.692 11.692 87.054 < 2.2e-16 ***
## Residuals 1715 230.344 0.134
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
The Analysis of Variance (ANOVA) table shows additional insight into
the significance of each predictor in explaining the variation in the
dependent variable (LNVMEDHVAL). For proportion of vacant
housing units (PCTVACANT), the sum of squares is 180.392,
indicating that those amount of variation in LNVMEDHVAL
that can be attributed to changes in PCTVACANT. A higher
sum of squares indicates a mhigher relationship between the predictor
and the dependent variable. The sum of squares for the percentage of
residents with a bachelor’s degree or higher (PCTBACHMOR)
explains the highest portion of the variance in LNVMEDHVAL.
In contrast, the sum of squares for the log-transformed number of
households living below the poverty line (LNNBELPOV100)
explains the least amount of variance in LNVMEDHVAL, with
only 11.69.
The total sum of squares, which represents the total variance in the
dependent variable (LNVMEDHVAL), is 230.34, with a mean
square error of 0.134. Overall, the ANOVA table provides a comprehensive
overview of the significance of each predictor in the model and the
proportion of variance explained by each predictor. It confirms that all
four predictors contribute significantly to explaining the variance in
the dependent variable. These findings provide strong evidence of the
robustness of the model and the relevance of neighbourhood
characteristics in predicting housing values.
Regression Assumptions Check
In this section, we conducted variety of analysis to check if the
assumption of the linear regression were met. In the earlier section, we
already checked the variable distribution and multicollinearity. Here,
we will check following assumption:
- Linearity
- Normality of Residuals
- Homoscedasticity
Linearity
To further examine the linear relationship between the dependent
variable and the predictors, we create four scatter plots, where the
x-axis represents each predictor and the y-axis represents the dependent
variable, Log Transformed Median House Value.
longer<-data %>%
pivot_longer(cols = c("PCTBACHMOR", "LNNBELPOV100", "PCTVACANT", "PCTSINGLES"),
names_to = "Variable",
values_to = "Value")
ggplot(longer,aes(x = Value, y = LNMEDHVAL)) +
geom_point(color = "black", size= 0.4) +
geom_smooth(method = "lm", color = "red", se = FALSE) +
facet_wrap(~ Variable, scales = "free", labeller = as_labeller(c(
"PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
"LNNBELPOV100" = "Logged Households Living in Poverty",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
))) +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8)) +
labs(title = "Scatter Plots of Dependent Variable vs. Predictors",
x = "Predictor Value",
y = "Log of Median House Value")

From the plots, we observe the following trends:
Logged Households Living in Poverty shows a
negative linear relationship with the dependent variable. As the
percentage of households living in poverty increases, the Log
Transformed Median House Value decreases. This is reflected in its
correlation coefficient \(< 0\). However, the association is not
strictly linear. In the graph, the points are more scattered widely,
particular at lower level of poverty, where housing values vary
significantly. This indicate while poverty levels have a negative impact
on housing values, the effect is not uniform across all block groups.
There is a substantial variation in housing values even at similar
poverty levels, which suggests that other factors may also be
influencing housing values.
% with Bachelor’s Degrees or Higher exhibits a
positive linear relationship with the dependent variable. When the
percentage of individuals with a bachelor’s degree or higher increases,
the Log Transformed Median House Value also rises, with a
correlation coefficient \(> 0\). The points on the graph form a tight
band along the trend line, indicating that higher education levels
within a neighborhood is highly correlated with higher housing values.
The consistent upward trend suggest that educational attainment is a key
driver of housing prices, and a clear linear trend implies that this
variable is suitable for this linear regression analysis.
% of Single House Units has a weaker but still
positive relationship with the dependent variable. While the trend is
not obvious, areas with a higher percentage of single-house units tend
to have higher Log Transformed Median House Values, especially
when the percentage is sufficiently large. The correlation coefficient
is \(> 0\). The scatter points shows significant variability in
housing values at various levels of single-house units, with some block
groups having high housing values despite a low percentage of
single-house units. This variability suggests that while there is a
positive relationship between single-house units and housing values,
other factors may also be influencing housing values at the same
time.
% of Vacant Houses has a general negative linear
relationship with the dependent variable. As the percentage of vacant
houses increases, the Log Transformed Median House Value
decreases, with a correlation coefficient \(< 0\). However, in the
graph, it reveals a more complex relationship with significant variation
in housing values across different vacancy rates. There are clusters of
block groups with high housing values and low vacancy rates, indicating
that the relationship is not strictly linear.In the middle and lower
ranges of vacancy rates, the decline in housing values becomes less
pronounced. This suggests that while vacant housing is associated with
lower property values, the impact diminishes or becomes less predictable
as the vacancy rate changes.
In summary, the scatterplot shows that while the PCTBACHMOR and
LNMEDHVAL have a clear linear relationship, the other predictors have
more complex non-linear relationships with the dependent variable. This
suggests that the linear regression model may not fully capture the
complexity of the relationships between the predictors and median house
values.
Normality of Residuals
Next, we examine the normality of residuals of the regression model.
The histogram of standardized residuals provides a detail view of the of
the distribution of the residuals from the OLS model, showing below:
ggplot(data, aes(x = Standardized_Residuals)) +
geom_histogram(bins = 30, fill = "black") +
labs(title = "Histogram of Standardized Residuals",
x = "Standardized Residuals",
y = "Frequency") +
theme_minimal() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

ggplot(data, aes(x = Fitted, y = Standardized_Residuals)) +
geom_point(color = "black", size= 0.4) +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
labs(
title = "Scatter Plot of Standardized Residuals vs Fitted Values",
x = "Predicted Values",
y = "Standardized Residuals"
) +
theme_minimal() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

join<- data %>%
dplyr::select(POLY_ID, Standardized_Residuals)
shape <- shape %>%
left_join(join, by = c("POLY_ID" = "POLY_ID"))
ggplot(shape)+
geom_sf(aes(fill = Standardized_Residuals), color = "transparent") +
scale_fill_gradientn(colors = c("#fff0f3", "#a4133c"),
name = "Std Residuals",
na.value = "transparent") + # Choose a color palette, invert direction if needed
labs(title = "Choropleth Map of Standardized Residuals") +
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8))

Additional Analysis
stepwise_model <- stepAIC(fit, direction = "both")
## Start: AIC=-3448.07
## LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100
##
## Df Sum of Sq RSS AIC
## <none> 230.34 -3448.1
## - PCTSINGLES 1 2.407 232.75 -3432.2
## - LNNBELPOV100 1 11.692 242.04 -3364.9
## - PCTVACANT 1 51.546 281.89 -3102.7
## - PCTBACHMOR 1 199.020 429.36 -2379.0
## Stepwise Model Path
## Analysis of Deviance Table
##
## Initial Model:
## LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100
##
## Final Model:
## LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100
##
##
## Step Df Deviance Resid. Df Resid. Dev AIC
## 1 1715 230.3435 -3448.073
lm <- trainControl(method = "cv", number = 5)
cvlm_model <- train(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=data, method = "lm", trControl = lm)
print(cvlm_model)
## Linear Regression
##
## 1720 samples
## 4 predictor
##
## No pre-processing
## Resampling: Cross-Validated (5 fold)
## Summary of sample sizes: 1376, 1376, 1376, 1376, 1376
## Resampling results:
##
## RMSE Rsquared MAE
## 0.3675194 0.6638375 0.2726991
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
cvlm_model_reduced = train(LNMEDHVAL ~ PCTVACANT + MEDHHINC, data = data, method = "lm", trControl = lm)
print(cvlm_model_reduced)
## Linear Regression
##
## 1720 samples
## 2 predictor
##
## No pre-processing
## Resampling: Cross-Validated (5 fold)
## Summary of sample sizes: 1376, 1376, 1376, 1376, 1376
## Resampling results:
##
## RMSE Rsquared MAE
## 0.4431696 0.5091175 0.3181327
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
Discussion
Our regression analysis of Philadelphia’s census block group data
clearly shows how neighborhood characteristics affect housing values.
Our model explains about 66% of the variation in the log-transformed
median house value (LNMEDHVAL). This indicates that factors such as the
percentage of vacant houses (PCTVACANT), the percentage of single-family
homes (PCTSINGLES), the percentage of residents with at least a
bachelor’s degree (PCTBACHMOR), and the log-transformed number of
households living below the poverty line (LNNBELPOV100) are all
important in shaping housing market outcomes.
Interpreting the Results:
Need to rewrite We cannot include log-transformed
value directly into the report, see the above interpret section for the
interpretation of the results.
Checking the Model Assumptions:
b) Talk about the quality of the model – that is, state if
this is a good model overall (e.g., R2, F-ratio test), and what other
predictors that we didn’t include in our model might be associated with
our dependent variable. i. Looking at the stepwise regression
results, did the final model include all 4 predictors or were some
dropped? What does that tell you about the quality of the model? ii.
Looking at the cross-validation results, was the RMSE better for the 4
predictor model or the 2 predictor model?
To validate our model, we performed stepwise regression using the
Akaike Information Criterion (AIC) and conducted 5-fold
cross-validation. The stepwise regression confirmed that the selected
predictors contribute to a strong model fit, while the cross-validation
results showed that the full model which includes all the four
predictors performs better than a reduced model that only includes the
percentage of vacant houses (PCTVACANT) and median household income.
These results strengthen our confidence in the predictive power and
robustness of the model.
Policy Implications: A Focus on Inclusive Growth and
Stability: (one paragraph only)
The findings have important implications for urban policy,
particularly in ensuring that strategies to improve housing markets do
not lead to displacement or increased housing burdens for vulnerable
communities. The strong negative impact of vacancy rates (PCTVACANT) on
housing values suggests that reducing long-term vacancies could play a
role in neighborhood stabilization. However, rather than policies that
solely focus on increasing property values, interventions should
prioritize equitable investment like rehabilitating vacant properties
for affordable housing, expanding community land trusts, and offering
support for longtime residents at risk of displacement.
Similarly, the strong relationship between educational attainment
(PCTBACHMOR) and housing values highlights the importance of expanding
access to high-quality education and workforce development. However,
increasing education levels alone does not ensure equitable housing
outcomes if housing costs rise beyond affordability for existing
residents. Thus, policies should be designed to balance educational
investment with affordability measures, such as rental assistance
programs and first-time homebuyer support for lower-income
households.
The negative association between poverty levels (LNNBELPOV100) and
housing values highlights the need for housing policies that actively
combat economic inequality and support affordable, stable communities.
Solutions such as mixed-income housing developments, income-based tax
credits, and expanded tenant protections can help ensure that economic
mobility does not come at the cost of displacement. The goal should be
to create stable, mixed-income communities where economic growth
benefits both current residents and new arrivals.
Limitations and Future Research:
Although our model provides a strong understanding of housing market
dynamics, there are several limitations that future research should
address. First, while our model explains a significant portion of the
variation in housing values, about one-third remains unexplained. This
suggests that other factors like access to transportation, historical
redlining patterns, or the presence of public amenities may play
important roles and should be explored in future studies.
The potential presence of spatial autocorrelation suggests that
neighboring block groups may not be entirely independent, which could
bias some estimates. Incorporating spatial econometric techniques, such
as spatial lag models or geographically weighted regression, could
improve the accuracy of future analyses.
Possibility of Ridge or LASSO Regression
Ridge and LASSO regression are used when there are highly correlated
predictors or when only a subset of features is expected to be truly
important. In such cases, some predictor coefficients may become
excessively large, leading to overfitting in a linear model. These
methods manage overfitting by adding a penalty term to the loss
function, which constrains the coefficients. However, in our model, the
highest correlation between predictors is 0.32, indicating no
significant multicollinearity. Additionally, no predictor exhibits
excessively large coefficients. Therefore, applying Ridge or LASSO
regression in this case would be unnecessary.
LS0tCnRpdGxlOiAnVXNpbmcgT0xTIFJlZ3Jlc3Npb24gdG8gUHJlZGljdCBNZWRpYW4gSG91c2UgVmFsdWVzIGluIFBoaWxhZGVscGhpYScKYXV0aG9yOiAiWmhhbmNoYW8gWWFuZywgSGFveXUgWmh1LCBLYXZhbmEgUmFqdSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogZmxhdGx5CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIG1hdGhqYXg6IGRlZmF1bHQKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlkeWNlbnN1cykKbGlicmFyeShrbml0cikgCmxpYnJhcnkoZ3QpIApsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ2djb3JycGxvdCkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoTUFTUykKbGlicmFyeShjYXJldCkKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgaW5jbHVkZT0gRkFMU0V9CiMgTG9hZCB0aGUgZGF0YQpkYXRhIDwtIHJlYWQuY3N2KCJkYXRhL1JlZ3Jlc3Npb25EYXRhLmNzdiIpCnNoYXBlIDwtIHN0X3JlYWQoImRhdGEvUmVncmVzc2lvbkRhdGEuc2hwIikKYGBgCgojIEludHJvZHVjdGlvbgpJbiByZWNlbnQgZGVjYWRlcywgUGhpbGFkZWxwaGlhIGhhcyBleHBlcmllbmNlZCBzdWJzdGFudGlhbCBjaGFuZ2VzIGluIHBvcHVsYXRpb24gZHluYW1pY3MsIGVjb25vbWljIGZsdWN0dWF0aW9ucywgYW5kIHJlZGV2ZWxvcG1lbnQgcHJlc3N1cmVzLiBBbW9uZyB0aGVzZSBjaGFuZ2VzLCBob3VzaW5nIHZhbHVlcyBoYXZlIGJlY29tZSBhIGtleSBpbmRpY2F0b3Igb2YgdGhlIHNvY2lvLWVjb25vbWljIGNvbmRpdGlvbnMgd2l0aGluIHRoZSBjaXR54oCZcyBuZWlnaGJvcmhvb2RzLiBSaXNpbmcgaG91c2luZyB2YWx1ZXMgdHlwaWNhbGx5IHJlZmxlY3QgYSBoaWdoZXIgcHJlc2VuY2Ugb2Ygd2VhbHRoaWVyIHJlc2lkZW50cyBvciBhIG5laWdoYm9yaG9vZCB1bmRlcmdvaW5nIGdlbnRyaWZpY2F0aW9uLCB3aGlsZSBkZWNsaW5pbmcgaG91c2luZyB2YWx1ZXMgb2Z0ZW4gc2lnbmFsIGluY3JlYXNlZCBlY29ub21pYyBwcmVzc3VyZSBvciBkZWNsaW5lLiBUaGVyZWZvcmUsIGFjY3VyYXRlbHkgZm9yZWNhc3RpbmcgdGhlIG1lZGlhbiBob3VzaW5nIHZhbHVlcyBhY3Jvc3MgUGhpbGFkZWxwaGlhIGlzIGNydWNpYWwgZm9yIHVyYmFuIHBsYW5uZXJzIGFuZCBwb2xpY3ltYWtlcnMsIGhlbHBpbmcgdGhlbSB0byBwcm9hY3RpdmVseSBhZGRyZXNzIHBvdGVudGlhbCByaXNrcyBzdWNoIGFzIGRpc3BsYWNlbWVudCBhbmQgZGlzaW52ZXN0bWVudC4gU3VwcG9ydGluZyBQaGlsYWRlbHBoaWHigJlzIGxvbmctdGVybSB2aXNpb24gb2YgZm9zdGVyaW5nIHZpYnJhbnQsIGRpdmVyc2UsIGFuZCByZXNpbGllbnQgY29tbXVuaXRpZXMgaXMgYWxzbyBlc3NlbnRpYWwuCgpUbyBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgcG90ZW50aWFsIGZhY3RvcnMgaW5mbHVlbmNpbmcgaG91c2luZyB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLCB3ZSBpZGVudGlmeSBzZXZlcmFsIGtleSB2YXJpYWJsZXM6IGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQsIHZhY2FuY3kgcmF0ZXMsIHRoZSBwcm9wb3J0aW9uIG9mIHNpbmdsZS1mYW1pbHkgaG9tZXMsIGFuZCBwb3ZlcnR5IGxldmVscy4gVGhlc2UgZmFjdG9ycyBhcmUgY2xvc2VseSByZWxhdGVkIHRvIGhvdXNpbmcgbWFya2V0IHRyZW5kcyBhbmQgcHJvdmlkZSBpbnNpZ2h0cyBpbnRvIHRoZSBuZWlnaGJvcmhvb2TigJlzIHNvY2lvLWVjb25vbWljIHN0YXR1cy4gCgpFZHVjYXRpb25hbCBhdHRhaW5tZW50IGlzIGNsb3NlbHkgbGlua2VkIHRvIHRoZSBzb2Npby1lY29ub21pYyBjaGFyYWN0ZXJpc3RpY3Mgb2YgbmVpZ2hib3Job29kcy4gSW5kaXZpZHVhbHMgd2l0aCBoaWdoZXIgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB0eXBpY2FsbHkgZWFybiBoaWdoZXIgaW5jb21lcyBhbmQgY29udHJpYnV0ZSBtb3JlIHRvIGxvY2FsIGVjb25vbWllcy4gQSBoaWdoZXIgY29uY2VudHJhdGlvbiBvZiBpbmRpdmlkdWFscyB3aXRoIGFkdmFuY2VkIGVkdWNhdGlvbmFsIGJhY2tncm91bmRzIHRlbmRzIHRvIGluY3JlYXNlIHRoZSBkZW1hbmQgZm9yIHdlbGwtZGVzaWduZWQgaG91c2luZyBpbiBhZmZsdWVudCBuZWlnaGJvcmhvb2RzLiBXaXRoIGEgY29uc2lzdGVudCBzdXBwbHksIGhvdXNpbmcgcHJpY2VzIGFuZCB2YWx1ZXMgYXJlIGxpa2VseSB0byByaXNlLiBTaW1pbGFybHksIGEgaGlnaCBwb3ZlcnR5IHJhdGUgYWxzbyBpbmRpY2F0ZXMgYSBkZWNsaW5pbmcgY29tbXVuaXR5LiBTaW5jZSBtYW55IHJlc2lkZW50cyBjYW5ub3QgYWZmb3JkIGx1eHVyeSBob3VzaW5nLCB0aGUgaG91c2luZyB2YWx1ZXMgaW4gdGhvc2UgbmVpZ2hib3Job29kcyBhcmUgbGlrZWx5IHRvIGJlIExvd2VyLgoKCkhpZ2ggdmFjYW5jeSByYXRlcyBvZnRlbiBjb3JyZWxhdGUgd2l0aCBkZWNsaW5pbmcgbmVpZ2hib3Job29kcyBhbmQgcmVkdWNlZCBtZWRpYW4gaG91c2UgdmFsdWVzLiBSZXNlYXJjaCBzaG93cyB0aGF0IHZhY2FudCBwcm9wZXJ0aWVzIGFmZmVjdCBtdWx0aXBsZSBmYWNldHMgb2YgY29tbXVuaXR5IGxpZmUsIHN1Y2ggYXMgaG91c2luZyBhbmQgbmVpZ2hib3Job29kIHZpdGFsaXR5LCBjcmltZSBwcmV2ZW50aW9uIGVmZm9ydHMsIGFuZCB0aGUgd2VsbC1iZWluZyBvZiBjb21tZXJjaWFsIGRpc3RyaWN0cy4gQXMgYSByZXN1bHQsIGFyZWFzIHdpdGggbnVtZXJvdXMgdmFjYW50IGhvdXNpbmcgdW5pdHMgdHlwaWNhbGx5IHNlZSBkaW1pbmlzaGVkIG1lZGlhbiBob3VzaW5nIHZhbHVlcy4gIAoKClRoZSBwcm9wb3J0aW9uIG9mIHNpbmdsZS1mYW1pbHkgaG9tZXMgaW4gYW4gYXJlYSBpbmZsdWVuY2VzIGhvdXNpbmcgdmFsdWVzLiBUaGVzZSBob21lcyBhcmUgZ2VuZXJhbGx5IHByaXZhdGUgYW5kIGNvbWZvcnRhYmxlLCBtYWtpbmcgdGhlbSBtb3JlIGRlc2lyYWJsZSBpbiBtYW55IFUuUy4gaG91c2luZyBtYXJrZXRzLiAgSG93ZXZlciwgdGhleSBhcmUgcmVsYXRpdmVseSBjb21tb24gaW4gc3VidXJiYW4gbmVpZ2hib3Job29kcyBhbmQgbWF5IHN1ZmZlciBmcm9tIGxvdyBhY2Nlc3NpYmlsaXR5IGFuZCBsaW1pdGVkIGluZnJhc3RydWN0dXJlLCB3aGljaCBjYW4gbmVnYXRpdmVseSBhZmZlY3QgdGhlaXIgcHJvcGVydHkgdmFsdWVzIGFzIHdlbGwuCgpJbiB0aGlzIHN0dWR5LCB3ZSB1dGlsaXplIG9yZGluYXJ5IGxlYXN0IHNxdWFyZXMgKE9MUykgcmVncmVzc2lvbiB0byBhbmFseXplIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVzZSBzb2Npb2Vjb25vbWljIGZhY3RvcnMgYW5kIG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLiBCeSBleGFtaW5pbmcgdGhlc2UgcmVsYXRpb25zaGlwcywgd2UgYWltIHRvIGlkZW50aWZ5IGNyaXRpY2FsIHByZWRpY3RvcnMgb2YgbWVkaWFuIGhvdXNpbmcgdmFsdWVzIHRocm91Z2hvdXQgUGhpbGFkZWxwaGlhIGFuZCBvZmZlciBpbnNpZ2h0cyBmb3IgZGVjaXNpb24tbWFrZXJzIGFuZCBjb21tdW5pdHkgaW5pdGlhdGl2ZXMuIAoKIyBNZXRob2RzCgojIyBEYXRhIENsZWFuaW5nCgpUbyBwcmVkaWN0IG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLCB3ZSBvYnRhaW5lZCB0aGUgb3JpZ2luYWwgZGF0YXNldCBmcm9tIHRoZSBVbml0ZWQgU3RhdGVzIENlbnN1cyBkYXRhLiBUaGUgZGF0YXNldCByZXByZXNlbnRzIGNlbnN1cyBibG9jayBncm91cHMgZnJvbSB0aGUgeWVhciAyMDAwIGFuZCBpbml0aWFsbHkgY29udGFpbmVkIDEsODE2IG9ic2VydmF0aW9ucy4gVGhlIGtleSB2YXJpYWJsZXMgaW5jbHVkZWQ6CgotICAqKlBPTFlfSUQqKiDigJMgQ2Vuc3VzIEJsb2NrIEdyb3VwIElECi0gICoqTUVESFZBTCoqIOKAkyBNZWRpYW4gdmFsdWUgb2YgYWxsIG93bmVyLW9jY3VwaWVkIGhvdXNpbmcgdW5pdHMKLSAgKipQQ0JBQ0hNT1JFKiog4oCTIFByb3BvcnRpb24gb2YgcmVzaWRlbnRzIGluIHRoZSBibG9jayBncm91cCB3aXRoIGF0IGxlYXN0IGEgYmFjaGVsb3LigJlzIGRlZ3JlZQotICAqKlBDVFZBQ0FOVCoqIOKAkyBQcm9wb3J0aW9uIG9mIGhvdXNpbmcgdW5pdHMgdGhhdCBhcmUgdmFjYW50Ci0gICoqUENUU0lOR0xFUyoqIOKAkyBQZXJjZW50YWdlIG9mIGhvdXNpbmcgdW5pdHMgdGhhdCBhcmUgZGV0YWNoZWQgc2luZ2xlLWZhbWlseSBob3VzZXMKLSAgKipOQkVMUE9WMTAwKiog4oCTIE51bWJlciBvZiBob3VzZWhvbGRzIHdpdGggaW5jb21lcyBiZWxvdyAxMDAlIG9mIHRoZSBwb3ZlcnR5IGxldmVsCi0gICoqTUVESEhJTkMqKiDigJMgTWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUKClRvIHJlZmluZSB0aGUgZGF0YXNldCBmb3IgbW9kZWxpbmcgcHVycG9zZXMsIHdlIGFwcGxpZWQgdGhlIGZvbGxvd2luZyBmaWx0ZXJpbmcgY3JpdGVyaWE6CgooMSkgUmV0YWluZWQgYmxvY2sgZ3JvdXBzIHdpdGggYSBwb3B1bGF0aW9uIGdyZWF0ZXIgdGhhbiA0MAooMikgSW5jbHVkZWQgb25seSBibG9jayBncm91cHMgdGhhdCBjb250YWluZWQgaG91c2luZyB1bml0cwooMykgRXhjbHVkZWQgcmVjb3JkcyB3aGVyZSB0aGUgbWVkaWFuIGhvdXNlIHZhbHVlIHdhcyBiZWxvdyAkMTAsMDAwCgpBZGRpdGlvbmFsbHksIHdlIHJlbW92ZWQgYSBzcGVjaWZpYyBibG9jayBncm91cCBpbiBOb3J0aCBQaGlsYWRlbHBoaWEgdGhhdCBleGhpYml0ZWQgaW5jb25zaXN0ZW5jaWVzLCB3aXRoIGFuIHVudXN1YWxseSBoaWdoIG1lZGlhbiBob3VzZSB2YWx1ZSAob3ZlciAkODAwLDAwMCkgZGVzcGl0ZSBhIHZlcnkgbG93IG1lZGlhbiBob3VzZWhvbGQgaW5jb21lIChsZXNzIHRoYW4gJDgsMDAwKS4KCkFmdGVyIGRhdGEgY2xlYW5pbmcsIHRoZSBmaW5hbCBkYXRhc2V0IGNvbnRhaW5lZCAxLDcyMCBvYnNlcnZhdGlvbnMuIAoKIyMgRXhwbG9yYXRvcnkgRGF0YSBBbmF5bHNpcwoKIyMjIFN1bW1hcnkgU3RhdGlzdGljcwpXZSB3aWxsIGZpcnN0IGV4YW1pbmUgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyAoICoqbWVhbioqIGFuZCAqKnN0YW5kYXJkIGRldmlhdGlvbiAoU0QpKiopIG9mIGtleSB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQsIGluY2x1ZGluZyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlcyAqTUVESFZBTCogKE1lZGlhbiBIb3VzZSBWYWx1ZSksIGFuZCBwcmVkaWN0b3JzICpOQkVMUE9WMTAwKiAoSG91c2Vob2xkcyBMaXZpbmcgaW4gUG92ZXJ0eSksICpQQ1RCQUNITU9SKiAoJSBvZiBJbmRpdmlkdWFscyB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciksICpQQ1RWQUNBTlQqKCUgb2YgVmFjYW50IEhvdXNlcyksICpQQ1RTSU5HTEVTKiggJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMpLiAKCiAKVGhlICoqbWVhbioqIChcKFxiYXJ7WH1cKSkgcmVwcmVzZW50cyB0aGUgYXZlcmFnZSB2YWx1ZSBvZiBhIHZhcmlhYmxlIGFuZCBpcyBjYWxjdWxhdGVkIGFzOiAgCgokJApcYmFye1h9ID0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV57bn0gWF9pCiQkICAKCndoZXJlOgoKLSBcKFhfaVwpIHJlcHJlc2VudHMgZWFjaCBpbmRpdmlkdWFsIG9ic2VydmF0aW9uICAKLSBcKG5cKSBpcyB0aGUgdG90YWwgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyAgCgpUaGUgbWVhbiBnaXZlcyB1cyBhIHNpbmdsZSByZXByZXNlbnRhdGl2ZSB2YWx1ZSBvZiB0aGUgZGF0YXNldC4gVG8gbWVhc3VyZSB2YXJpYWJpbGl0eSwgd2UgdXNlIHRoZSAqKnN0YW5kYXJkIGRldmlhdGlvbiAoU0QpKiosIHdoaWNoIHF1YW50aWZpZXMgaG93IG11Y2ggdGhlIHZhbHVlcyBpbiBhIGRhdGFzZXQgZGV2aWF0ZSBmcm9tIHRoZSBtZWFuLiBUaGUgZm9ybXVsYSBmb3IgdGhlIHNhbXBsZSBzdGFuZGFyZCBkZXZpYXRpb24gKFwoc1wpKSBpczogIAoKJCQKcyA9IFxzcXJ0e1xmcmFjezF9e24tMX0gXHN1bV97aT0xfV57bn0gXGxlZnQoIFhfaSAtIFxiYXJ7WH0gXHJpZ2h0KV4yfQokJAoKd2hlcmU6CgotIFwoWF9pXCkgcmVwcmVzZW50cyBlYWNoIGluZGl2aWR1YWwgb2JzZXJ2YXRpb24gIAotIFwoXGJhcntYfVwpIGlzIHRoZSBtZWFuIG9mIHRoZSBvYnNlcnZhdGlvbnMgIAotIFwoblwpIGlzIHRoZSB0b3RhbCBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zICAKCkEgbGFyZ2VyIHN0YW5kYXJkIGRldmlhdGlvbiBpbmRpY2F0ZXMgdGhhdCB0aGUgZGF0YSBwb2ludHMgYXJlIG1vcmUgc3ByZWFkIG91dCwgd2hpbGUgYSBzbWFsbGVyIHN0YW5kYXJkIGRldmlhdGlvbiBzdWdnZXN0cyB0aGF0IHRoZSBkYXRhIHBvaW50cyBhcmUgY2xvc2VyIHRvIHRoZSBtZWFuLiAgCgoKIyMjIERpc3RyaWJ1dGlvbnMgCgpXZSB3aWxsIGFsc28gZXhhbWluZSB0aGUgaGlzdG9ncmFtcyBhbmQgYXBwbHkgbG9nIHRyYW5zZm9ybWF0aW9ucyBmb3Iga2V5IHZhcmlhYmxlcyB0byBhc3Nlc3Mgd2hldGhlciB0aGUgdHJhbnNmb3JtZWQgdmFyaWFibGVzIGZvbGxvdyBhIG1vcmUgbm9ybWFsLWxpa2UgZGlzdHJpYnV0aW9uLiAKCioqSGlzdG9ncmFtcyoqIHByb3ZpZGUgYSB2aXN1YWwgcmVwcmVzZW50YXRpb24gb2YgaG93IGEgdmFyaWFibGUncyB2YWx1ZXMgYXJlIGRpc3RyaWJ1dGVkLCBoZWxwaW5nIHRvIGlkZW50aWZ5IHdoZXRoZXIgdGhlIGRhdGEgZm9sbG93cyBhICoqbm9ybWFsIGRpc3RyaWJ1dGlvbioqLCBpcyAqKnJpZ2h0LXNrZXdlZCoqLCBvciAqKmxlZnQtc2tld2VkKiouIExpbmVhciByZWdyZXNzaW9uIG1vZGVsIGFzc3VtZSB0aGF0IHZhcmlhYmxlcyBhcmUgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZC4gIAoKLSAqKlgtYXhpczoqKiBUaGUgdmFsdWVzIG9mIHRoZSB2YXJpYWJsZSAoZS5nLiwgaG91c2UgcHJpY2VzLCBpbmNvbWUgbGV2ZWxzKS4gCgotICoqWS1heGlzOioqIFRoZSBmcmVxdWVuY3kgb2Ygb2JzZXJ2YXRpb25zIHdpdGhpbiBlYWNoIGJpbi4gIAoKSWYgdGhlIGhpc3RvZ3JhbSBpcyAqKnJpZ2h0LXNrZXdlZCoqLCBpdCBzdWdnZXN0cyB0aGF0IGEgc21hbGwgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBoYXZlIHNpZ25pZmljYW50bHkgaGlnaGVyIHZhbHVlcyBjb21wYXJlZCB0byB0aGUgcmVzdC4gRm9yIHZhcmlhYmxlcyBmb2xsb3dpbmcgYSAqKnJpZ2h0LXNrZXdlZCBkaXN0cmlidXRpb24qKiwgd2Ugd2lsbCBhcHBseSBhICoqbG9nIHRyYW5zZm9ybWF0aW9uKiogdG8gdGhlc2UgdmFyaWFibGVzIHRvIGltcHJvdmUgbm9ybWFsaXR5LiBTaW5jZSB0aGUgKipsb2cgdHJhbnNmb3JtYXRpb24qKiBpcyB1bmRlZmluZWQgZm9yIHplcm8gb3IgbmVnYXRpdmUgdmFsdWVzLCB3ZSBtdXN0IGZpcnN0IGNoZWNrIHdoZXRoZXIgYW55IHZhcmlhYmxlIGNvbnRhaW5zIHplcm8uCgotIElmICoqbm8gemVyb3MqKiBwcmVzZW50cywgd2UgYXBwbHkgdGhlIHN0YW5kYXJkIGxvZyB0cmFuc2Zvcm1hdGlvbjogIAokJAogIFgnID0gXGxvZ197MTB9IChYKQokJCAgCi0gSWYgKip6ZXJvcyoqIHByZXNlbnQsIHdlIGFkanVzdCBieSBhZGRpbmcgMSBiZWZvcmUgdGFraW5nIHRoZSBsb2c6ICAKJCQKICBYJyA9IFxsb2dfezEwfSAoWCArIDEpCiQkICAKICBUaGlzIGVuc3VyZXMgdGhhdCBhbGwgdmFsdWVzIHJlbWFpbiBwb3NpdGl2ZSBhbmQgYXZvaWRzIHVuZGVmaW5lZCB2YWx1ZXMuICAKCkJ5IGNvbXBhcmluZyB0aGUgKipvcmlnaW5hbCBoaXN0b2dyYW1zKiogd2l0aCB0aGUgKipsb2ctdHJhbnNmb3JtZWQgaGlzdG9ncmFtcyoqLCB3ZSB3aWxsIGFzc2VzcyB3aGV0aGVyIHRoZSB0cmFuc2Zvcm1hdGlvbiBpbXByb3ZlcyB0aGUgc3VpdGFiaWxpdHkgb2YgdGhlIGRhdGEgZm9yIHByZWRpY3RpdmUgbW9kZWxpbmcuCgoKIyMjIENvcnJlbGF0aW9ucwoKV2Ugd2lsbCBhbmFseXplICoqY29ycmVsYXRpb25zKiogYmV0d2VlbiBwcmVkaWN0b3JzLCB0byBkZXRlY3QgcG90ZW50aWFsICoqbXVsdGljb2xsaW5lYXJpdHkqKiBiZWZvcmUgcHJvY2VlZGluZyB3aXRoIHJlZ3Jlc3Npb24gYW5hbHlzaXMsIHdoaWNoIGNhbiBkaXN0b3J0IG1vZGVsIGludGVycHJldGF0aW9ucy4gIAoKTXVsdGljb2xsaW5lYXJpdHkgb2NjdXJzIHdoZW4gcHJlZGljdG9ycyBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQsIHdoaWNoIGNhbiBsZWFkIHRvIHVuc3RhYmxlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzLiBJdCBhbHNvIGluZmxhdGVzIHN0YW5kYXJkIGVycm9ycywgcmVkdWNpbmcgdGhlIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBvZiBwcmVkaWN0b3JzLCBhbmQgaW5jcmVhc2VzIHRoZSByaXNrIG9mIG92ZXJmaXR0aW5nLCBhcyByZWR1bmRhbnQgdmFyaWFibGVzIGRvIG5vdCBjb250cmlidXRlIG5ldyBpbmZvcm1hdGlvbiB0byB0aGUgbW9kZWwuICAKClRoZSAqKmNvcnJlbGF0aW9uIGNvZWZmaWNpZW50KiogXChyXCkgaXMgY2FsY3VsYXRlZCBhczogIAoKJCQKciA9IFxmcmFje1xzdW1fe2k9MX1ee259ICh4X2kgLSBcYmFye3h9KSh5X2kgLSBcYmFye3l9KX17XHNxcnR7XHN1bV97aT0xfV57bn0gKHhfaSAtIFxiYXJ7eH0pXjIgXHN1bV97aT0xfV57bn0gKHlfaSAtIFxiYXJ7eX0pXjJ9fQokJApJbiBhIG1vcmUgY29uY2lzZSB3YXksIHRoaXMgYWJvdmUgZm9ybXVsYSBpcyBhbHNvIGVxdWl2YWxlbnQgdG8gdGhlIGZvbGxvd2luZzogCgokJApyID0gXGZyYWN7MX17bi0xfSBcc3VtX3tpPTF9XntufSBcbGVmdCggXGZyYWN7eF9pIC0gXGJhcnt4fX17U194fSBccmlnaHQpIFxsZWZ0KCBcZnJhY3t5X2kgLSBcYmFye3l9fXtTX3l9IFxyaWdodCkKJCQKd2hlcmU6ICAKLSBcKFhfaVwpIGFuZCBcKFlfaVwpIGFyZSBpbmRpdmlkdWFsIGRhdGEgcG9pbnRzIGZvciB2YXJpYWJsZXMgXChYXCkgYW5kIFwoWVwpLCByZXNwZWN0aXZlbHkuICAKLSBcKFxiYXJ7WH1cKSBhbmQgXChcYmFye1l9XCkgYXJlIHRoZSAqKm1lYW4gdmFsdWVzKiogb2YgXChYXCkgYW5kIFwoWVwpLiAgCi0gVGhlIG51bWVyYXRvciByZXByZXNlbnRzIHRoZSAqKmNvdmFyaWFuY2UqKiBiZXR3ZWVuIFwoWFwpIGFuZCBcKFlcKSwgd2hpbGUgdGhlIGRlbm9taW5hdG9yICoqbm9ybWFsaXplcyoqIHRoZSB2YWx1ZXMuICAKClRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBcKHJcKSByYW5nZXMgZnJvbSAqKi0xIHRvIDEqKjogQSB2YWx1ZSBvZiArMSBpbmRpY2F0ZXMgYSBwZXJmZWN0IHBvc2l0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAsIHdoaWxlIGEgdmFsdWUgb2YgLTEgaW5kaWNhdGVzIGEgcGVyZmVjdCBuZWdhdGl2ZSBsaW5lYXIgcmVsYXRpb25zaGlwLiBBIHZhbHVlIG9mIDAgc3VnZ2VzdHMgbm8gbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMsIG1lYW5pbmcgY2hhbmdlcyBpbiBvbmUgZG8gbm90IGluZmx1ZW5jZSB0aGUgb3RoZXIuCgojIyBNdWx0aXBsZSBSZWdyZXNzaW9uCkFmdGVyIGdldHRpbmcgYSBnZW5lcmFsIHNlbnNlIG9mIHRoZSBkYXRhLCB3ZSBjb25kdWN0IG11bHRpcGxlIHJlZ3Jlc3Npb24gYW5hbHlzaXMgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSwgKipNZWRpYW4gSG91c2UgVmFsdWUgKE1FREhWQUwpKiosIGFuZCB0aGUgcHJlZGljdG9ycywgKiplZHVjYXRpb24gYXR0YWlubWVudCAoUENUQkFDSE1PUikqKiwgKipudW1iZXIgb2YgSG91c2Vob2xkcyBMaXZpbmcgaW4gUG92ZXJ0eSAoTkJFTFBPVjEwMCkqKiwgKipwZXJjZW50YWdlIG9mIFZhY2FudCBIb3VzZXMgKFBDVFZBQ0FOVCkqKiwgYW5kICoqcGVyY2VudGFnZSBvZiBTaW5nbGUgSG91c2UgVW5pdHMgKFBDVFNJTkdMRVMpKiouIFJlZ3Jlc3Npb24gYW5hbHlzaXMgaXMgYSBzdGF0aXN0aWNhbCBtZXRob2QgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIG9uZSBvciBtb3JlIHByZWRpY3RvcnMuIFdpdGggdGhpcyB0eXBlIG9mIGFuYWx5c2lzLCByZXNlYXJjaGVycyBjYW4gaWRlbnRpZnkgdGhlIHN0cmVuZ3RoIGFuZCBkaXJlY3Rpb24gb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHZhcmlhYmxlcywgbWFrZSBwcmVkaWN0aW9ucywgYW5kIGFzc2VzcyB0aGUgc2lnbmlmaWNhbmNlIG9mIHByZWRpY3RvcnMuIFRoZSBtb2RlbCBhbHNvIGVzdGltYXRlcyBjb2VmZmljaWVudHMgZm9yIGVhY2ggcHJlZGljdG9yLCB3aGljaCByZXByZXNlbnQgdGhlIGV4cGVjdGVkIGNoYW5nZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGZvciBhIG9uZS11bml0IGNoYW5nZSBpbiB0aGUgcHJlZGljdG9yLCBob2xkaW5nIG90aGVyIHByZWRpY3RvcnMgY29uc3RhbnQuIEZvciB0aGlzIHN0dWR5LCB0aGUgbXVsdGlwbGUgcmVncmVzc2lvbiBtb2RlbCBpcyBmb3JtdWxhdGVkIGFzIGZvbGxvd3M6CiQkClx0ZXh0e0xOTUVESFZBTH0gPSBcYmV0YV8wICsgXGJldGFfMSBcdGV4dHtQQ1RWQUNBTlR9ICsgXGJldGFfMiBcdGV4dHtQQ1RTSU5HTEVTfSArIFxiZXRhXzMgXHRleHR7UENUQkFDSE1PUn0gKyBcYmV0YV80IFx0ZXh0e2xvZyhOQkVMUE9WMTAwKX0gKyBcZXBzaWxvbgokJAp3aGVyZSAqKkxOTUVESFZBTCoqIGlzIHRoZSBsb2ctdHJhbnNmb3JtZWQgbWVkaWFuIGhvdXNlIHZhbHVlLCAqKlBDVFZBQ0FOVCoqIGlzIHRoZSBwcm9wb3J0aW9uIG9mIHZhY2FudCBob3VzaW5nIHVuaXRzICwgKipQQ1RTSU5HTEVTKiogaXMgdGhlIHByb3BvcnRpb24gb2YgdGhlIHNpbmdsZSBmYW1pbHkgaG91c2luZyAsICoqUENUQkFDSE1PUioqIGlzIHRoZSBwZXJjZW50YWdlIG9mIHRoZSByZXNpZGVudHMgaG9sZGluZyBiYWNoZWxvcidzIGRlZ3JlZSBvciBoaWdoZXIsIGFuZCAqKmxvZyhOQkVMUE9WMTAwKSoqICBpcyB0aGUgbG9nLXRyYW5zZm9ybWVkIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBiZWxvdyB0aGUgcG92ZXJ0eSBsaW5lLgoKXChcYmV0YV8wXCkgaXMgdGhlIGludGVyY2VwdCwgXChcYmV0YV8xXCksIFwoXGJldGFfMlwpLCBcKFxiZXRhXzNcKSwgYW5kIFwoXGJldGFfNFwpIGFyZSB0aGUgY29lZmZpY2llbnRzIGZvciBlYWNoIHByZWRpY3RvciwgYW5kIFwoXGVwc2lsb25cKSBpcyB0aGUgZXJyb3IgdGVybS4gVGhlIGNvZWZmaWNpZW50IFwoXGJldGFfMVwpLCBcKFxiZXRhXzJcKSwgXChcYmV0YV8zXCksIFwoXGJldGFfNFwpIHJlcHJlc2VudCB0aGUgY2hhbmdlIGluIHRoZSBsb2ctdHJhbnNmb3JtZWQgbWVkaWFuIGhvdXNlIHZhbHVlIGZvciBhIG9uZS11bml0IGNoYW5nZSBpbiB0aGUgY29ycmVzcG9uZGluZyBwcmVkaWN0b3IsIGhvbGRpbmcgb3RoZXIgcHJlZGljdG9ycyBjb25zdGFudC4gVGhlIGVycm9yIHRlcm0gXChcZXBzaWxvblwpIGFjY291bnRzIGZvciB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSB0aGF0IGlzIG5vdCBleHBsYWluZWQgYnkgdGhlIHByZWRpY3RvcnMuCgojIyMgUmVncmVzc2lvbiBBc3N1bXB0aW9ucwoKVGhlcmUgYXJlIHNldmVyYWwgYXNzdW1wdGlvbnMgYXNzb2NpYXRlZCB3aXRoIHJlZ3Jlc3Npb24gYW5hbHlzaXMgdGhhdCBuZWVkIHRvIGJlIG1ldCBmb3IgdGhlIHJlc3VsdHMgdG8gYmUgdmFsaWQuIFRoZXNlIGFzc3VtcHRpb25zIGluY2x1ZGluZyAqKmxpbmVhcml0eSoqLCAqKmluZGVwZW5kZW5jZSBvZiBvYnNlcnZhdGlvbnMqKiwgKipob21vc2NlZGFzdGljaXR5KiosICoqbm9ybWFsaXR5IG9mIHJlc2lkdWFscyoqLCAqKm5vIG11bHRpY29sbGluZWFyaXR5KiosIGFuZCAqKm5vIGZld2VyIHRoYW4gMTAgb2JzZXJ2YXRpb25zIHBlciBwcmVkaWN0b3JzKiouCgpGaXJzdCwgKipMaW5lYXJpdHkqKiBhc3N1bWVzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIHRoZSBwcmVkaWN0b3JzIGlzIGxpbmVhci4gVG8gdmVyaWZ5IHRoaXMgYXNzdW1wdGlvbiwgd2UgbWFkZSBzY2F0dGVyIHBsb3RzIG9mIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYWdhaW5zdCBlYWNoIHByZWRpY3Rvci4gSWYgdGhlIHJlbGF0aW9uc2hpcCBhcHBlYXJzIHRvIGJlIGxpbmVhciwgdGhlIGFzc3VtcHRpb25zIHdhcyBtZXQuCgpTZWNvbmQsICoqSW5kZXBlbmRlbmNlIG9mIE9ic2VydmF0aW9ucyoqIGFzc3VtZXMgdGhhdCB0aGUgb2JzZXJ2YXRpb25zIGFyZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyLiBUaGVyZSBzaG91bGQgYmUgbm8gc3BhdGlhbCBvciB0ZW1wb3JhbCBvciBvdGhlciBmb3JtcyBvZiBkZXBlbmRlbmNlIGluIHRoZSBkYXRhLiAKClRoaXJkLCAqKkhvbW9zY2VkYXN0aWNpdHkqKiBhc3N1bWVzIHRoYXQgdGhlIHZhcmlhbmNlIG9mIHRoZSByZXNpZHVhbHMgXChcZXBzaWxvblwpIGlzIGNvbnN0YW50IHJlZ2FyZGxlc3Mgb2YgdGhlIHZhbHVlcyBvZiBlYWNoIGxldmVsIG9mIHRoZSBwcmVkaWN0b3JzLiBUbyBjaGVjayB0aGlzIGFzc3VtcHRpb24sIHdlIG1hZGUgYSBzY2F0dGVyIHBsb3Qgb2YgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYWdhaW5zdCB0aGUgcHJlZGljdGVkIHZhbHVlcy4gSWYgdGhlIHJlc2lkdWFscyBhcmUgZXZlbmx5IHNwcmVhZCBhcm91bmQgemVybywgdGhlIGFzc3VtcHRpb24gd2FzIG1ldC4gQW55IHBhdHRlcm5zIG1heSBpbmRpY2F0ZSB0aGUgcHJlc2VuY2Ugb2YgaGV0ZXJvc2NlZGFzdGljaXR5LgoKRm91cnRoLCAqKk5vcm1hbGl0eSBvZiBSZXNpZHVhbHMqKiBhc3N1bWVzIHRoYXQgdGhlIHJlc2lkdWFscyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIFdlIGV4YW1pbmVkIHRoZSBoaXN0b2dyYW0gb2YgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgdG8gY2hlY2sgaWYgdGhleSBhcmUgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZC4gSWYgdGhlIGhpc3RvZ3JhbSBpcyBiZWxsLXNoYXBlZCwgdGhlIGFzc3VtcHRpb24gd2FzIG1ldC4KCkZpZnRoLCAqKk5vIE11bHRpY29sbGluZWFyaXR5KiogYXNzdW1lcyB0aGF0IHRoZSBwcmVkaWN0b3JzIGFyZSBub3QgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLiBXZSBjYWxjdWxhdGVkIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXggb2YgdGhlIHByZWRpY3RvcnMgdG8gY2hlY2sgZm9yIG11bHRpY29sbGluZWFyaXR5LiBJZiB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGFyZSBpcyBub3QgZ3JlYXRlciB0aGFuIDAuOCBvciBsZXNzIHRoYW4gLTAuOCwgdGhlIGFzc3VtcHRpb24gd2FzIG1ldC4KCkZpbmFsbHksICoqTm8gRmV3ZXIgdGhhbiAxMCBPYnNlcnZhdGlvbnMgcGVyIFByZWRpY3RvcioqIGFzc3VtZXMgdGhhdCB0aGVyZSBhcmUgYXQgbGVhc3QgMTAgb2JzZXJ2YXRpb25zIGZvciBlYWNoIHByZWRpY3RvciBpbiB0aGUgbW9kZWwuIFNpbmNlIHRoZXJlIGFyZSBvdmVyIDEsNzAwIG9ic2VydmF0aW9ucyBpbiB0aGUgZGF0YXNldCwgdGhpcyBhc3N1bXB0aW9uIHdhcyBtZXQuCgojIyMgUGFyYW1ldGVyIEVzdGltYXRpb25zCgpBZnRlciB2ZXJpZmluZyB0aGUgYXNzdW1wdGlvbnMgb2YgdGhlIHJlZ3Jlc3Npb24sIHdlIHN0YXJ0IHRoZSByZWdyZXNzaW9uIGFuYWx5c2lzLiBTZXZlcmFsIHBhcmFtZXRlcnMgbmVlZCB0byBlc3RpbWF0ZSBoZXJlOiAKLSBcKCBcYmV0YV8wIFwpLCB3aGljaCBpcyB0aGUgaW50ZXJjZXB0Ci0gXCggXGJldGFfMSwgXGRvdHMsIFxiZXRhX2sgXCksIHdoaWNoIGFyZSBjb2VmZmljaWVudHMgb2YgZWFjaCBpbmRlcGVuZGVudCB2YXJpYWJsZXMKLSBcKCBcc2lnbWFeMiBcKSwgdGhlIHZhcmlhbmNlIG9mIHRoZSBlcnJvciB0ZXJtcywgd2hpY2ggcmVwcmVzZW50cyB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSB0aGF0IGlzIG5vdCBleHBsYWluZWQgYnkgdGhlIHByZWRpY3RvcnMuCgpUaGUgbGVhc3Qgc3F1YXJlcyBtZXRob2QgZXN0aW1hdGVzIHRoZSBjb2VmZmljaWVudHMgYnkgbWluaW1pemluZyAqKnRoZSBzdW0gb2Ygc3F1YXJlZCBlcnJvcnMgKFNTRSkqKiwgd2hpY2ggaXMgdGhlIHN1bSBvZiB0aGUgc3F1YXJlZCBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBvYnNlcnZlZCB2YWx1ZXMgYW5kIHRoZSBwcmVkaWN0ZWQgdmFsdWVzLiBUaGUgZm9ybXVsYSBmb3IgU1NFIGlzOgoKJCQKXHRleHR7U1NFfSA9IFxzdW1fe2k9MX1ee259ICh5X2kgLSBcaGF0e3l9X2kpXjIgPSBcc3VtX3tpPTF9XntufSAoeV9pIC0gXGhhdHtcYmV0YX1fMCAtIFxoYXR7XGJldGF9XzEgeF97aTF9IC0gXGRvdHMgLSBcaGF0e1xiZXRhfV9rIHhfe2lrfSleMgokJAp3aGVyZSBcKHlfaVwpIGlzIHRoZSBhY3R1YWwgb3Igb2JzZXJ2ZWQgdmFsdWUsIFwoXGhhdHt5fV9pXCkgaXMgdGhlIHByZWRpY3RlZCB2YWx1ZSwgXChcaGF0e1xiZXRhfV8wLCBcZG90cywgXGhhdHtcYmV0YX1fa1wpIGFyZSB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50cywgYW5kIFwoeF97aTF9LCBcZG90cywgeF97aWt9XCkgYXJlIHRoZSBwcmVkaWN0b3IgdmFsdWVzIGZvciB0aGUgXChpXCktdGggb2JzZXJ2YXRpb24uCgpXaXRoIHRoZSBFcnJvciBTdW0gb2YgU3F1YXJlcyAoU1NFKSBjYWxjdWxhdGVkLCB3ZSBjYW4gZXN0aW1hdGUgdGhlIHZhcmlhbmNlIG9mIHRoZSBlcnJvciB0ZXJtcyBcKFxzaWdtYV4yXCkgdXNpbmcgdGhlIGZvcm11bGE6CgokJApcc2lnbWFeMiA9IFxmcmFje1x0ZXh0e1NTRX19e24gLSAoaysxKX0KJCQKd2hlcmUgXChuXCkgaXMgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgYW5kIFwoa1wpIGlzIHRoZSBudW1iZXIgb2YgcHJlZGljdG9ycyBpbiB0aGUgbW9kZWwuCgojIyMgTW9kZWwgRXZhbHVhdGlvbgoKV2UgZXZhbHVhdGVkIHRoZSBtb2RlbCdzIGZpdG5lc3MgdXNpbmcgdGhlIGNvZWZmaWNpZW50IG9mIGRldGVybWluYXRpb24gXChSXjJcKSBhbmQgdGhlIGFkanVzdGVkIFwoUl4yXCkuIFRoZSBjb2VmZmljaWVudCBvZiBkZXRlcm1pbmF0aW9uIFwoUl4yXCkgbWVhc3VyZXMgdGhlIHByb3BvcnRpb24gb2YgdmFyaWFuY2UgaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSB0aGF0IGlzIGV4cGxhaW5lZCBieSB0aGUgcHJlZGljdG9ycy4gVGhlIGFkanVzdGVkIFwoUl4yXCkgYWRqdXN0cyB0aGUgXChSXjJcKSB2YWx1ZSBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMsIHdoaWNoIGhlbHAgdG8gcHJvdmlkZSBhIG1vcmUgYWNjdXJhdGUgbWVhc3VyZSBvZiBtb2RlbCBmaXQgZm9yIG11bHRpcGxlIHJlZ3Jlc3Npb24sIGFzIHRoZSBpbmNyZWFzZSB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgY2FuIGFydGlmaWNpYWxseSBpbmZsYXRlIHRoZSBcKFJeMlwpIHZhbHVlLgoKVG8gb2J0YWluIFwoUl4yXCksIFwoU1NUXCkgb3IgdGhlIHRvdGFsIHN1bSBvZiBzcXVhcmVzLCBuZWVkZWQgdG8gYmUgY2FsY3VsYXRlZCBmaXJzdC4gVGhlIFwoU1NUXCkgbWVhc3VyZXMgdGhlIHRvdGFsIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUsIGdpdmVuIGJ5OgokJApTU1QgPSBcc3VtX3tpPTF9XntufSAoeV9pIC0gXGJhcnt5fSleMgokJApXaGVyZSBcKHlfaVwpIGlzIHRoZSBvYnNlcnZlZCB2YWx1ZSwgYW5kIFwoXGJhcnt5fVwpIGlzIHRoZSBtZWFuIG9mIHRoZSBvYnNlcnZlZCB2YWx1ZS4gVGhlbiwgdGhlIFwoUl4yXCkgY2FuIGJlIG9idGFpbmVkIGJ5OgokJApSXjIgPSAxIC0gXGZyYWN7U1NFfXtTU1R9CiQkCkFmdGVyIHRoYXQsIFwoUl4yXCkgaXMgYWRqdXN0ZWQgYXMgZm9sbG93cyBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBcKG5cKSBhbmQgdGhlIG51bWJlciBvZiBwcmVkaWN0b3JzIFwoa1wpOgokJApSXjJfe1x0ZXh0e2Fkan19ID0gMSAtIFxmcmFjeygxIC0gUl4yKShuIC0gMSl9e24gLSBrIC0gMX0KJCQKCiMjIyBIeXBvdGhlc2lzIFRlc3RpbmcKCkluIHRoaXMgYW5hbHlzaXMuIHNldmVyYWwgaHlwb3RoZXNpcyB0ZXN0cyBhcmUgY29uZHVjdGVkIHRvIGRldGVybWluZSB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZSBtb2RlbCBhbmQgaXRzIHByZWRpY3RvcnMuIFRoZSBvdmVyYWxsIHNpZ25pZmljYW5jZSBvZiB0aGUgbW9kZWwgaXMgYXNzZXNzZWQgdXNpbmcgdGhlIEYtcmF0aW8uIEl0IGNvbXBhcmVzIHRoZSB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlIG1vZGVsIHRvIHRoZSB2YXJpYW5jZSBub3QgZXhwbGFpbmVkIGJ5IHRoZSBtb2RlbC5BIGhpZ2hlciBGLXJhdGlvIGluZGljYXRlcyB0aGF0IHRoZSBtb2RlbCBleHBsYWlucyBhIHNpZ25pZmljYW50IGFtb3VudCBvZiB2YXJpYW5jZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGNvbXBhcmVkIHRvIHRoZSByZXNpZHVhbCB2YXJpYW5jZS4gCgpUaGUgbnVsbCBoeXBvdGhlc2lzIGFuZCBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIGZvciB0aGUgRi1yYXRpbyBhcmUgc3RhdGVkIGFzIGZvbGxvd3M6CgotIFRoZSAqKm51bGwgaHlwb3RoZXNpcyBcKEhfMFwpKiogc3RhdGVzIHRoYXQgYWxsIGNvZWZmaWNpZW50cyBhcmUgZXF1YWwgdG8gemVybywgbWVhbmluZyB0aGF0IHRoZSBwcmVkaWN0b3JzIGRvIG5vdCBleHBsYWluIHRoZSB2YXJpYW5jZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChtZWRpYW4gaG91c2UgdmFsdWUpLiBTdGF0ZWQgYXM6CgogICQkCiAgSF8wOiBcYmV0YV8xID0gXGJldGFfMiA9IFxiZXRhXzMgPSBcYmV0YV80ID0gMAogICQkCi0gVGhlICoqYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyBcKEhfYVwpKiogc3RhdGVzIHRoYXQgYXQgbGVhc3Qgb25lIGNvZWZmaWNpZW50IGlzIG5vdCBlcXVhbCB0byB6ZXJvLiBJbiBvdXIgY2FzZSwgdGhpcyBtZWFucyB0aGF0IGF0IGxlYXN0IG9uZSBwcmVkaWN0b3IgZXhwbGFpbnMgdGhlIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKG1lZGlhbiBob3VzZSB2YWx1ZSkuIFN0YXRlZCBhczoKICAkJAogIEhfYTogXHRleHR7QXQgbGVhc3Qgb25lIH0gXGJldGFfaSBcbmVxIDAKICAkJAoKV2UgYWxzbyBjb25kdWN0IGEgdC10ZXN0IHRvIGRldGVybWluZSB0aGUgc2lnbmlmaWNhbmNlIG9mIGVhY2ggaW5kaXZpZHVhbCBwcmVkaWN0b3IgaW4gdGhlIG1vZGVsOgoKLSBUaGUgKipudWxsIGh5cG90aGVzaXMgXChIX3swaX1cKSoqIHN0YXRlcyB0aGF0IHRoZSBjb2VmZmljaWVudCBmb3IgdGhlIHByZWRpY3RvciBpIGlzIGVxdWFsIHRvIHplcm8sIG1lYW5pbmcgdGhhdCB0aGUgcHJlZGljdG9yIGRvZXMgbm90IGV4cGxhaW4gdGhlIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKG1lZGlhbiBob3VzZSB2YWx1ZSkuIFN0YXRlZCBhczoKCiAgJCQKICBIX3swaX06IFxiZXRhX2kgPSAwCiAgJCQKICAKLSBUaGUgKiphbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIFwoSF97YWl9XCkqKiBzdGF0ZXMgdGhhdCB0aGUgY29lZmZpY2llbnQgZm9yIHRoZSBwcmVkaWN0b3IgaSBpcyBub3QgZXF1YWwgdG8gemVybywgbWVhbmluZyB0aGF0IHRoZSBwcmVkaWN0b3IgZXhwbGFpbnMgdGhlIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKG1lZGlhbiBob3VzZSB2YWx1ZSkuIFN0YXRlZCBhczoKICAKICAkJAogIEhfe2FpfTogXGJldGFfaSBcbmVxIDAKICAkJAogIAojIyBBZGRpdGlvbmFsIEFuYWx5c2lzCgojIyMgU3RlcHdpc2UgUmVncmVzc2lvbgoKSW4gYWRkaXRpb24gdG8gdGhlIG11bHRpcGxlIHJlZ3Jlc3Npb24gYW5hbHlzaXMsIHdlIGNvbmR1Y3Qgc3RlcHdpc2UgcmVncmVzc2lvbiBhbmFseXNpcyB0byBpZGVudGlmeSB0aGUgbW9zdCBzaWduaWZpY2FudCBwcmVkaWN0b3JzIG9mIG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLiBTdGVwd2lzZSByZWdyZXNzaW9uIGlzIGEgbWV0aG9kIHRoYXQgYXV0b21hdGljYWxseSBzZWxlY3RzIHRoZSBiZXN0IHN1YnNldCBvZiBwcmVkaWN0b3JzIGZvciB0aGUgbW9kZWwuIEl0IGludm9sdmVzIGFkZGluZyBvciByZW1vdmluZyBwcmVkaWN0b3JzIGJhc2VkIG9uIHRoZWlyIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSAoUC12YWx1ZSkgYW5kIHRoZSBBSUMgKEFrYWlrZSBJbmZvcm1hdGlvbiBDcml0ZXJpb24pLiBUaGUgc3RlcHdpc2UgcmVncmVzc2lvbiBhbmFseXNpcyB3aWxsIGhlbHAgdXMgaWRlbnRpZnkgdGhlIG1vc3QgaW1wb3J0YW50IHByZWRpY3RvcnMgYW5kIGltcHJvdmUgdGhlIG92ZXJhbGwgbW9kZWwgZml0cy4KCkhvd2V2ZXIsIHRoZXJlIGFyZSBzZXZlcmFsIGxpbWl0YXRpb25zIHRvIHN0ZXB3aXNlIHJlZ3Jlc3Npb24uIEZpcnN0LCB0aGUgZmluYWwgc3RlcHdpc2UgcmVncmVzc2lvbiBtb2RlbCBpcyBub3QgZ3VhcmFudGVlZCB0byBiZSBvcHRpbWFsIGluIGFueSBzcGVjaWZpYyBzZW5zZS4gVGhlcmUgbWF5IGJlIG90aGVyIG1vZGVscyB0aGF0IGFyZSBhcyBnb29kIGFzLCBvciBldmVuIGJldHRlciB0aGFuIHRoZSBvbmUgc2VsZWN0ZWQgYnkgc3RlcHdpc2UgcmVncmVzc2lvbiwgYnV0IHRoZSBwcm9jZWR1cmUgb25seSB5ZWlsZHMgYSBzaW5nbGUgbW9kZWwuIFNlY29uZCwgdGhlIHN0ZXB3aXNlIHJlZ3Jlc3Npb24gZG9lcyB0YWtlIGludG8gYWNjb3VudCByZXNlYXJjaGVycycga25vd2xlZGdlIGFib3V0IHRoZSBwcmVkaWN0b3JzLiBJbXBvcnRhbnQgdmFyaWFibGVzIG1heSBiZSBleGNsdWRlIGZyb20gdGhlIG1vZGVsIGlmIHRoZXkgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgaW5pdGlhbGx5LiBNb3Jlb3ZlciwgVGhpcyBtZXRob2QgYWxzbyBydW5zIHRoZSByaXNrIG9mIFR5cGUgSSBhbmQgVHlwZSBJSSBlcnJvcnPigJRtZWFuaW5nIGl0IG1heSBpbmNsdWRlIHVuaW1wb3J0YW50IHZhcmlhYmxlcyBvciBleGNsdWRlIGltcG9ydGFudCBvbmVzLiAKCiMjIyBDcm9zcy1WYWxpZGF0aW9uCgpUbyBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIHJlZ3Jlc3Npb24gbW9kZWwsIHdlIGNvbmR1Y3QgSy1mb2xkIGNyb3NzLXZhbGlkYXRpb24uIENyb3NzLXZhbGlkYXRpb24gaXMgYSB0ZWNobmlxdWUgdXNlZCB0byBldmx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgcHJlZGljdGl2ZSBtb2RlbHMuIEluIEstZm9sZCBDcm9zcy1WYWxpZGF0aW9uLCB0aGUgZGF0YXNldCBpcyByYW5kb21seSBkaXZpZGVkIGludG8gSyBlcXVhbC1zaXplZCBmb2xkcy4gVGhlIG1vZGVsIGlzIHRyYWluZWQgb24gSy0xIGZvbGRzIGFuZCB0ZXN0ZWQgb24gdGhlIHJlbWFpbmluZyBmb2xkLiBUaGlzIHByb2Nlc3MgaXMgcmVwZWF0ZWQgSyB0aW1lcywgd2l0aCBlYWNoIGZvbGQgc2VydmluZyBhcyB0aGUgdGVzdCBzZXQgZXhhY3RseSBvbmNlLiBUaGUgYXZlcmFnZSBwZXJmb3JtYW5jZSBhY3Jvc3MgYWxsIEsgZm9sZHMgaXMgdGhlbiBjYWxjdWxhdGVkLiBDcm9zcy12YWxpZGF0aW9uIGhlbHBzIHRvIGFzc2VzcyB0aGUgbW9kZWwncyBnZW5lcmFsaXphdGlvbiBwZXJmb3JtYW5jZSBhbmQgcmVkdWNlIHRoZSByaXNrIG9mIG92ZXJmaXR0aW5nLgoKSW4gb3VyIGFuYWx5c2lzLCB3ZSB1c2VkIEs9NSwgd2hpY2ggaXMgYSBjb21tb24gY2hvaWNlIGZvciBjcm9zcy12YWxpZGF0aW9uLiBUaGUgcm9vdCBtZWFuIHNxdWFyZWQgZXJyb3IgKFJNU0UpIGlzIHVzZWQgdG8gY29tcGFyZSB0aGUgcGVyZm9ybWFuY2Ugb2YgZGlmZmVyZW50IG1vZGVscy4gVGhlIFJNU0UgbWVhc3VyZXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcHJlZGljdGVkIHZhbHVlcyBhbmQgdGhlIGFjdHVhbCB2YWx1ZXMuIEEgbG93ZXIgdmFsdWUgb2YgUk1TRSBpbmRpY2F0ZXMgYSBiZXR0ZXIgcHJlZGljdGl2ZSBtb2RlbC4KClRoZSBtZWFuIHNxdWFyZSBlcnJvcnMgaXMgY2FsY3VsYXRlZCBhcyBmb2xsb3dzOgokJCAKXHRleHR7TVNFfSA9IFxmcmFjezF9e259IFxzdW1fe2k9MX1ee259ICh5X2kgLSBcaGF0e3l9X2kpXjIgCiQkCkFuZCB0aGUgcm9vdCBtZWFuIHNxdWFyZSBlcnJvcnMgKFJNU0UpIGlzIHRoZSBzcXVhcmUgcm9vdCBvZiB0aGUgbWVhbiBzcXVhcmUgZXJyb3JzIChNU0UpOgokJApcdGV4dHtSTVNFfSA9IFxzcXJ0e1x0ZXh0e01TRX19CiQkCgojIyBTb2Z0d2FyZSBhbmQgUGFja2FnZXMKCkluIHRoaXMgYW5hbHlzaXMsIHdlIHV0aWxpemUgdGhlIFIgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UsIGEgcHJvZmVzc2lvbmFsIHN0YXRpc3RpY2FsIHNvZnR3YXJlIHdpZGVseSB1c2VkIGZvciBkYXRhIGFuYWx5c2lzIGFuZCB2aXN1YWxpemF0aW9uLlRoZSBmb2xsb3dpbmcgbGlicmFyaWVzIGFuZCBwYWNrYWdlcyBoYXZlIGJlZW4gZW1wbG95ZWQgdG8gY29uZHVjdCB0aGUgYW5hbHlzaXM6CgotIGB0aWR5dmVyc2VgOiBBIGNvbGxlY3Rpb24gb2YgUiBwYWNrYWdlcyBmb3IgZGF0YSBtYW5pcHVsYXRpb24gYW5kIHZpc3VhbGl6YXRpb24uCi0gYHNmYDogQSBwYWNrYWdlIGZvciBzcGF0aWFsIGRhdGEgcHJvY2Vzc2luZywgZXNwZWNpYWxseSBmb3IgaGFuZGxpbmcgc2hhcGVmaWxlcy4KLSBgZ2dwbG90MmA6IEEgcG9wdWxhciB2aXN1YWxpemF0aW9uIHBhY2thZ2UgZm9yIGNyZWF0aW5nIGhpZ2gtcXVhbGl0eSBtYXAgYW5kIGNoYXJ0cywgcGFydCBvZiB0aGUgYHRpZHl2ZXJzZWAgY29sbGVjdGlvbi4KLSBgZ2djb3JycGxvdGA6IEEgcGFja2FnZSBkZXNpZ25hdGVkIHRvICB2aXN1YWxpemUgY29ycmVsYXRpb24gbWF0cmljZXMgdXNpbmcgYGdncGxvdDJgLgotIGBwYXRjaHdvcmtgOiBBIHBhY2thZ2UgZm9yIGNvbWJpbmluZyBtdWx0aXBsZSBnZ3Bsb3QyIHBsb3RzIGludG8gYSBzaW5nbGUgcGxvdC4KLSBgTUFTU2A6IEEgcGFja2FnZSBwcm92aWRlcyBtdWx0aXBsZSBmdW5jdGlvbnMgYW5kIGRhdGFzZXRzIGZvciBzdGF0aXN0aWNhbCBhbmFseXNpcywgaW5jbHVkaW5nIGxpbmVhciBtb2RlbHMuIAotIGBjYXJldGA6IEEgcGFja2FnZSBmb3IgY3JlYXRpbmcgcHJlZGljdGl2ZSBtb2RlbHMgYW5kIGNvbmR1Y3RpbmcgbWFjaGluZSBsZWFybmluZyB0YXNrcywgdXNlZCBpbiBjcm9zcy12YWxpZGF0aW9uIGFuZCBrLWZvbGQgYW5hbHlzaXMuCi0gYGthYmxlRXh0cmFgOiBBIHBhY2thZ2UgZm9yIGNyZWF0aW5nIHRhYmxlcyB3aXRoIGFkdmFuY2VkIGZvcm1hdHRpbmcgb3B0aW9ucy4KCiMgUmVzdWx0cwoKIyMgRXhwbG9yYXRvcnkgUmVzdWx0cyAKClRoZSB0YWJsZSBiZWxvdyBwcmVzZW50cyB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzIGZvciB0aGUga2V5IHZhcmlhYmxlcywgYW4gb3ZlcnZpZXcgb2YgdGhlIGNlbnRyYWwgdGVuZGVuY3kgYW5kIHZhcmlhYmlsaXR5LiBUaGUgZGVwZW5kZW50IHZhcmlhYmxlICptZWRpYW4gaG91c2UgdmFsdWUqIGhhcyBhIG1lYW4gb2YgNjYsMjg3LjczLCBpbmRpY2F0aW5nIHRoYXQgdGhlIGF2ZXJhZ2UgbWVkaWFuIGhvdXNlIHZhbHVlIGJ5IGNlbnN1cyB0cmFjdCBpbiBQaGlsYWRlbHBoaWEgaXMgYXBwcm94aW1hdGVseSA2NiwyODcuNzMgZG9sbGFyLiBUaGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIDYwLDAwNi4wOCBkb2xsYXIgc3VnZ2VzdHMgdGhhdCBob3VzZSB2YWx1ZXMgZXhoaWJpdCBzaWduaWZpY2FudCB2YXJpYWJpbGl0eSBhY3Jvc3MgY2Vuc3VzIHRyYWN0cy4KCkZvciB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcywgYWxsIGhhdmUgc3RhbmRhcmQgZGV2aWF0aW9ucyBjbG9zZSB0byBvciBncmVhdGVyIHRoYW4gdGhlIG1lYW4sIGluZGljYXRpbmcgbGFyZ2UgZGlmZmVyZW5jZXMgaW4gZWR1Y2F0aW9uYWwgYXR0YWlubWVudCwgZWNvbm9taWMgc3RhdHVzLCBob3VzaW5nIG9jY3VwYW5jeSwgYW5kIGhvdXNpbmcgc3RydWN0dXJlIGNvbXBvc2l0aW9uIGFjcm9zcyBQaGlsYWRlbHBoaWEncyBjZW5zdXMgYmxvY2sgZ3JvdXBzLgoKYGBge3Igc3VtbWFyeSBzdGF0cywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZGVwZW5kZW50X3ZhciA8LSAiTUVESFZBTCIKCnByZWRpY3RvcnMgPC0gYygiUENUQkFDSE1PUiIsICJOQkVMUE9WMTAwIiwgIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIikKCnN1bW1hcnlfc3RhdHMgPC0gZGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KGFsbF9vZihjKGRlcGVuZGVudF92YXIsIHByZWRpY3RvcnMpKSkgJT4lCiAgc3VtbWFyaXNlX2FsbChsaXN0KE1lYW4gPSBtZWFuLCBTRCA9IHNkKSwgbmEucm0gPSBUUlVFKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiVmFyaWFibGUiLCB2YWx1ZXNfdG8gPSAiVmFsdWUiKSAlPiUKICBzZXBhcmF0ZShWYXJpYWJsZSwgaW50byA9IGMoIlZhcmlhYmxlIiwgIlN0YXQiKSwgc2VwID0gIl8iKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gU3RhdCwgdmFsdWVzX2Zyb20gPSBWYWx1ZSkKCgoKc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSA8LSByZWNvZGUoc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSwKICAiTUVESFZBTCIgPSAiTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAiTkJFTFBPVjEwMCIgPSAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAiUENUQkFDSE1PUiIgPSAiJSBvZiBJbmRpdmlkdWFscyB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciIsCiAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCikKCgoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIG11dGF0ZSgKICAgIE1lYW4gPSByb3VuZChNZWFuLCAyKSwKICAgIFNEID0gcm91bmQoU0QsIDIpCiAgKQoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIGFycmFuZ2UoVmFyaWFibGUgPT0gIk1lZGlhbiBIb3VzZSBWYWx1ZSIpCgpwcmVkaWN0b3Jfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlICE9ICJNZWRpYW4gSG91c2UgVmFsdWUiKQpkZXBlbmRlbnRfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlID09ICJNZWRpYW4gSG91c2UgVmFsdWUiKQoKIyBEZXRlcm1pbmUgdGhlIHN0YXJ0IGFuZCBlbmQgcm93cyBmb3IgZWFjaCBncm91cApzdGFydF9wcmVkIDwtIG1pbihwcmVkaWN0b3Jfcm93cykKZW5kX3ByZWQgICA8LSBtYXgocHJlZGljdG9yX3Jvd3MpCnN0YXJ0X2RlcCAgPC0gbWluKGRlcGVuZGVudF9yb3dzKQplbmRfZGVwICAgIDwtIG1heChkZXBlbmRlbnRfcm93cykKCiMgQ3JlYXRlIHRoZSB0YWJsZSB1c2luZyBrYWJsZSBhbmQgYWRkIGV4dHJhIGZvcm1hdHRpbmcKa2FibGUoc3VtbWFyeV9zdGF0cywgY2FwdGlvbiA9ICJTdW1tYXJ5IFN0YXRpc3RpY3MiLCAKICAgICAgYWxpZ24gPSBjKCJsIiwgImwiLCAibCIpLCBib29rdGFicyA9IFRSVUUsIGVzY2FwZSA9IEZBTFNFICkgJT4lCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDEsICJTdGF0aXN0aWNzIiA9IDIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lCiAgZ3JvdXBfcm93cygiUHJlZGljdG9ycyIsIHN0YXJ0X3ByZWQsIGVuZF9wcmVkKSAlPiUKICBncm91cF9yb3dzKCJEZXBlbmRlbnQgVmFyaWFibGUiLCBzdGFydF9kZXAsIGVuZF9kZXApJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBUUlVFKQoKYGBgCgoKIyMjIEhpc3RvZ3JhbSBEaXN0cmlidXRpb24KCk9uZSBvZiB0aGUgYXNzdW1wdGlvbnMgb2YgT0xTIHJlZ3Jlc3Npb24gaXMgdGhhdCB2YXJpYWJsZXMgZm9sbG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gVG8gYXNzZXNzIHRoZSBkaXN0cmlidXRpb24gb2Yga2V5IHZhcmlhYmxlcywgdGhlaXIgaGlzdG9ncmFtcyBhcmUgcHJlc2VudGVkIGJlbG93LiBBcyBzZWVuIGluIHRoZSBwbG90cywgYWxsIGtleSB2YXJpYWJsZXMgZXhoaWJpdCBsZWZ0LXNrZXduZXNzLCBtZWFuaW5nIHRoZWlyIGRpc3RyaWJ1dGlvbnMgYXJlIHJpZ2h0LXNrZXdlZCAocG9zaXRpdmVseSBza2V3ZWQpLCB3aXRoIGEgY29uY2VudHJhdGlvbiBvZiBzbWFsbGVyIHZhbHVlcyBhbmQgYSBsb25nIHJpZ2h0IHRhaWwuCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KI2NoZWNrIDAKY29sdW1uc190b19jaGVjayA8LSBjKGRlcGVuZGVudF92YXIsIHByZWRpY3RvcnMpCgp6ZXJvX2NvdW50cyA8LSBzYXBwbHkoZGF0YVtjb2x1bW5zX3RvX2NoZWNrXSwgZnVuY3Rpb24oeCkgc3VtKHggPT0gMCwgbmEucm0gPSBUUlVFKSkKCnplcm9fY291bnRzW3plcm9fY291bnRzID4gMF0KCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTksIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9Cmxvbmdlcl92ZXJzaW9uPC0gZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIk1FREhWQUwiLCAiUENUQkFDSE1PUiIsICJOQkVMUE9WMTAwIiwgIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXJfdmVyc2lvbixhZXMoeCA9IFZhbHVlKSkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5jb3VudC4uKSwgZmlsbCA9ICJibGFjayIsIGFscGhhID0gMC43KSArICAKICBmYWNldF93cmFwKH5WYXJpYWJsZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMywgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihjKAogICAgIk1FREhWQUwiID0gIk1lZGlhbiBIb3VzZSBWYWx1ZSIsCiAgICAiUENUQkFDSE1PUiIgPSAiJSB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciIsCiAgICAiTkJFTFBPVjEwMCIgPSAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAgICJQQ1RWQUNBTlQiID0gIiUgb2YgVmFjYW50IEhvdXNlcyIsCiAgICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCiAgKSkpICsgIAogIGxhYnMoeCA9ICJWYWx1ZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJIaXN0b2dyYW1zIG9mIERlcGVuZGVudCBhbmQgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKYGBgCgpUbyBtZWV0IHRoZSBub3JtYWxpdHkgYXNzdW1wdGlvbiBvZiBPTFMsIGxvZyB0cmFuc2Zvcm1hdGlvbiBpcyBhcHBsaWVkIHdoZXJlIG5lY2Vzc2FyeSB0byBpbXByb3ZlIGRpc3RyaWJ1dGlvbmFsIHN5bW1ldHJ5LiBUaGlzIHRyYW5zZm9ybWF0aW9uIGhlbHBzIG5vcm1hbGl6ZSB0aGUgZGlzdHJpYnV0aW9ucywgbWFraW5nIHRoZW0gbW9yZSBzdWl0YWJsZSBmb3IgcmVncmVzc2lvbiBhbmFseXNpcy4gVGhlIGhpc3RvZ3JhbXMgb2YgdGhlIGxvZy10cmFuc2Zvcm1lZCB2YXJpYWJsZXMgaW5kaWNhdGUgYSBtb3JlIG5vcm1hbC1saWtlIGRpc3RyaWJ1dGlvbi4gSG93ZXZlciwgc29tZSBzbGlnaHQgc2tld25lc3MgcmVtYWluczogdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAoKkxvZyBNZWRpYW4gSG91c2UgVmFsdWUqKSBhbmQgdGhlIHByZWRpY3RvciAoKkxvZyAlIFNpbmdsZSBIb3VzZSBWYWx1ZSopIGFyZSBzbGlnaHRseSBsZWZ0LXNrZXdlZCwgd2hpbGUgdGhlIHByZWRpY3RvcnMgKkxvZyAlIEhvdXNlaG9sZHMgaW4gUG92ZXJ0eSogYW5kICpMb2cgJSBWYWNhbnQgSG91c2VzKiBhcmUgc2xpZ2h0bHkgcmlnaHQtc2tld2VkLgpgYGB7cn0KZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZSgKICAgIExOTUVESFZBTCA9IGxvZyhNRURIVkFMKSwKICAgIExOUENUQkFDSE1PUiA9IGxvZygxK1BDVEJBQ0hNT1IpLAogICAgTE5OQkVMUE9WMTAwID0gbG9nKDErTkJFTFBPVjEwMCksCiAgICBMTlBDVFZBQ0FOVCA9IGxvZygxK1BDVFZBQ0FOVCksCiAgICBMTlBDVFNJTkdMRVMgPSBsb2coMStQQ1RTSU5HTEVTKQogICkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbG9uZ2VyX3ZlcnNpb24yIDwtIGRhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKExOTUVESFZBTCwgTE5QQ1RCQUNITU9SICxMTk5CRUxQT1YxMDAsTE5QQ1RWQUNBTlQsIExOUENUU0lOR0xFUyksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXJfdmVyc2lvbjIsYWVzKHggPSBWYWx1ZSkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uY291bnQuLiksIGZpbGwgPSAicmVkIiwgYWxwaGEgPSAwLjcpICsgIAogIGZhY2V0X3dyYXAoflZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAzLCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGMoCiAgICAiTE5NRURIVkFMIiA9ICJMb2cgTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAgICJMTlBDVEJBQ0hNT1IiID0gIkxvZyAlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZSIsCiAgICAiTE5OQkVMUE9WMTAwIiA9ICJMb2cgIyBIb3VzZWhvbGRzIGluIFBvdmVydHkiLAogICAgIkxOUENUVkFDQU5UIiA9ICJMb2cgJSBWYWNhbnQgSG91c2VzIiwKICAgICJMTlBDVFNJTkdMRVMiID0gIkxvZyAlIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgKyAgCiAgbGFicyh4ID0gIlZhbHVlIiwgeSA9ICJDb3VudCIsIHRpdGxlID0gIkhpc3RvZ3JhbXMgb2YgRGVwZW5kZW50IGFuZCBsb2cgdHJhbnNmb3JtZWQgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKYGBgCgoKT3RoZXIgcmVncmVzc2lvbiBhc3N1bXB0aW9ucyB3aWxsIGJlIGFzc2Vzc2VkIHNlcGFyYXRlbHkgaW4gdGhlIFJlZ3Jlc3Npb24gQXNzdW1wdGlvbiBDaGVja3Mgc2VjdGlvbiBsYXRlci4KCiMjIyBDaG9yb3BsZXRoIE1hcHMKCkxpbmVhcml0eSBhc3N1bWVzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIHRoZSBwcmVkaWN0b3JzIGlzIGxpbmVhci4gVG8gZXhhbWluZSB0aGlzIHJlbGF0aW9uc2hpcCwgd2UgYW5hbHl6ZSB0aGUgc3BhdGlhbCBkaXN0cmlidXRpb24gb2Yga2V5IHZhcmlhYmxlcy4gQ2VydGFpbiBwcmVkaWN0b3IgbWFwcyBleGhpYml0IHBhdHRlcm5zIHNpbWlsYXIgdG8gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSwgc3VnZ2VzdGluZyBhIHN0cm9uZyBwb3RlbnRpYWwgcmVsYXRpb25zaGlwLgoKQmVsb3cgaXMgdGhlIGNob3JvcGxldGggbWFwIG9mIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUsICpMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlKi4gSXQgcmV2ZWFscyB0aGF0IGNlbnRyYWwgY2l0eSBhcmVhcyBhbmQgR2VybWFudG93bi9DaGVzdG51dCBIaWxsIGhhdmUgaGlnaGVyIG1lZGlhbiBob3VzZSB2YWx1ZXMsIHdoaWxlIE5vcnRoIFBoaWxhZGVscGhpYSBoYXMgbG93ZXIgdmFsdWVzLiAgCgoKYGBge3IsZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OSx3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpnZ3Bsb3Qoc2hhcGUpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gTE5NRURIVkFMKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3JzID0gYygiI2ZmZjBmMyIsICIjYTQxMzNjIiksIAogICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiTE5NRURIVkFMIiwgCiAgICAgICAgICAgICAgICAgICAgICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiKSArIAogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5IiwgZmlsbCA9IE5BLCBzaXplID0gMC44KSkgKwogIGxhYnModGl0bGUgPSAiTG9nIFRyYW5zZm9ybWVkIE1lZGlhbiBIb3VzZSBWYWx1ZSIpCmBgYAoKVG8gdW5kZXJzdGFuZCB0aGUgc3BhdGlhbCByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCBwcmVkaWN0b3JzLCB3ZSBwcmVzZW50IGZvdXIga2V5IHByZWRpY3RvciBtYXBzIGJlbG93IGFzIHdlbGwuIAoKYGBge3IsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0Kc2hwZV9sb25nZXI8LSBzaGFwZSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiwgIlBDVEJBQ0hNT1IiLCAiTE5OQkVMUE9WIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKY3VzdG9tX3RpdGxlcyA8LSBjKAogIFBDVFZBQ0FOVCAgID0gIlBlcmNlbnQgb2YgVmFjYW50IEhvdXNlcyIsCiAgUENUU0lOR0xFUyAgPSAiUGVyY2VudCBvZiBTaW5nbGUgSG91c2UgVW5pdHMiLAogIFBDVEJBQ0hNT1IgID0gIlBlcmNlbnQgb2YgQmFjaGVsb3IncyBEZWdyZWUgb3IgSGlnaGVyIiwKICBMTk5CRUxQT1YgICA9ICJMb2dnZWQgVHJhbnNmb3JtZWQgUG92ZXJ0eSBSYXRlIgopCgoKCnBsb3RfbGlzdCA8LSBsYXBwbHkodW5pcXVlKHNocGVfbG9uZ2VyJFZhcmlhYmxlKSwgZnVuY3Rpb24odmFyX25hbWUpIHsKICBkYXRhX3N1YnNldCA8LSBzdWJzZXQoc2hwZV9sb25nZXIsIFZhcmlhYmxlID09IHZhcl9uYW1lKQogIAogIGdncGxvdChkYXRhX3N1YnNldCkgKwogICAgZ2VvbV9zZihhZXMoZmlsbCA9IFZhbHVlKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50bigKICAgICAgY29sb3JzID0gYygiI2ZmZjBmMyIsICIjYTQxMzNjIiksCiAgICAgIG5hbWUgPSB2YXJfbmFtZSwKICAgICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiCiAgICApICsKICAgIGxhYnModGl0bGUgPSBjdXN0b21fdGl0bGVzW1t2YXJfbmFtZV1dKSArCiAgICB0aGVtZSgKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjMsICJjbSIpLAogICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIpLAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleSIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuOCkKICAgICkKfSkKCiMgQ29tYmluZSB0aGUgcGxvdHMgaW50byBhIGdyaWQgKDIgY29sdW1ucyBieSAyIHJvd3MpCmNvbWJpbmVkX3Bsb3QgPC0gKHBsb3RfbGlzdFtbMV1dICsgcGxvdF9saXN0W1syXV0pIC8KICAgICAgICAgICAgICAgICAocGxvdF9saXN0W1szXV0gKyBwbG90X2xpc3RbWzRdXSkKCmNvbWJpbmVkX3Bsb3QKYGBgCgpUaGVzZSBtYXBzIGFsc28gaGVscCBpZGVudGlmeSB3aGV0aGVyIHByZWRpY3RvcnMgYXJlIGNsb3NlbHkgcmVsYXRlZCB0byBlYWNoIG90aGVyLCB3aGljaCBjb3VsZCBjYXVzZSBtdWx0aWNvbGxpbmVhcml0eSBwcm9ibGVtcy4gVGhlICpQZXJjZW50IG9mIEJhY2hlbG9yJ3MgRGVncmVlIG9yIEhpZ2hlciogbWFwIGxvb2tzIHZlcnkgc2ltaWxhciB0byB0aGUgKkxvZyBUcmFuc2Zvcm1lZCBNZWRpYW4gSG91c2UgVmFsdWUqIG1hcCwgc3VnZ2VzdGluZyB0aGF0IGFyZWFzIHdpdGggbW9yZSBjb2xsZWdlIGdyYWR1YXRlcyB0ZW5kIHRvIGhhdmUgaGlnaGVyIGhvdXNlIHZhbHVlcy4gQWxzbywgdGhlICpQZXJjZW50IG9mIFZhY2FudCBIb3VzZXMqIGFuZCAqUGVyY2VudCBvZiBTaW5nbGUgSG91c2UgVW5pdHMqIG1hcHMgc2hhcmUgYSBzaW1pbGFyIHBhdHRlcm7igJROb3J0aCBQaGlsYWRlbHBoaWEgYW5kIFVuaXZlcnNpdHkgQ2l0eSBoYXZlIGEgaGlnaCBwZXJjZW50YWdlIG9mIHZhY2FudCBob3VzZXMgYW5kIGEgbG93IHBlcmNlbnRhZ2Ugb2Ygc2luZ2xlLWhvdXNlIHVuaXRzLCB3aGlsZSBHZXJtYW50b3duL0NoZXN0bnV0IEhpbGwgYW5kIEZhciBOb3J0aGVhc3QgUGhpbGFkZWxwaGlhIHNob3cgdGhlIG9wcG9zaXRlIHRyZW5kLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlc2UgdHdvIHByZWRpY3RvcnMgbWF5IGJlIHN0cm9uZ2x5IHJlbGF0ZWQsIHdoaWNoIGNvdWxkIGxlYWQgdG8gbXVsdGljb2xsaW5lYXJpdHkgaXNzdWVzIGluIHRoZSByZWdyZXNzaW9uIGFuYWx5c2lzLgoKIyMjIEV4YW1pbmluZyBNdWx0aWNvbGxpbmVhcml0eSAmIENvcnJlbGF0aW9uIE1hdHJpeAoKVG8gZnVydGhlciBleGFtaW5lIG11bHRpY29sbGluZWFyaXR5LCB3ZSBjcmVhdGUgYSBjb3JyZWxhdGlvbiBtYXRyaXggYmV0d2VlbiBwcmVkaWN0b3JzLiBBbGwgY29ycmVsYXRpb24gdmFsdWVzIGFyZSBiZWxvdyAwLjcsIGluZGljYXRpbmcgdGhhdCBubyBzZXZlcmUgbXVsdGljb2xsaW5lYXJpdHkgb2NjdXJzIGluIG91ciBtb2RlbC4gIAoKQW1vbmcgdGhlbSwgKiolIG9mIFNpbmdsZSBIb3VzZSBVbml0cyoqIGFuZCAqKkxvZ2dlZCBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5KiogaGF2ZSBhIGNvcnJlbGF0aW9uIG9mIC0wLjMyLCBzdWdnZXN0aW5nIHNvbWUgcmVsYXRpb25zaGlwIGJ1dCBub3Qgc3Ryb25nIGVub3VnaCB0byBjYXVzZSBzZXZlcmUgbXVsdGljb2xsaW5lYXJpdHkuIExvb2tpbmcgYmFjayBhdCB0aGUgY2hvcm9wbGV0aCBtYXBzIG9mIHRoZXNlIHR3byBwcmVkaWN0b3JzLCB0aGVpciBzcGF0aWFsIHBhdHRlcm5zIGFyZSBub3Qgc2ltaWxhci4gKiolIG9mIFNpbmdsZSBIb3VzZSBVbml0cyoqIGFuZCAqKiUgb2YgSW5kaXZpZHVhbHMgd2l0aCBhIEJhY2hlbG9yJ3MgRGVncmVlIG9yIEhpZ2hlcioqIGhhdmUgYSBjb3JyZWxhdGlvbiBvZiAtMC4zLCBhZ2FpbiBpbmRpY2F0aW5nIHNvbWUgcmVsYXRpb25zaGlwIHdpdGhvdXQgc2V2ZXJlIG11bHRpY29sbGluZWFyaXR5LiBUaGUgY2hvcm9wbGV0aCBtYXBzIG9mIHRoZXNlIHR3byBwcmVkaWN0b3JzIGFsc28gZG8gbm90IGV4aGliaXQgc2ltaWxhciBzcGF0aWFsIHBhdHRlcm5zLiBBZGRpdGlvbmFsbHksIHdoaWxlIHRoZSBjaG9yb3BsZXRoIG1hcHMgb2YgKipQZXJjZW50IG9mIFZhY2FudCBIb3VzZXMqKiBhbmQgKipQZXJjZW50IG9mIFNpbmdsZSBIb3VzZSBVbml0cyoqIHNoYXJlIGEgc2ltaWxhciBwYXR0ZXJuLCBhcyBtZW50aW9uZWQgYmVmb3JlLCB0aGVpciBjb3JyZWxhdGlvbiB2YWx1ZSBpcyBvbmx5IDAuMiwgc3VnZ2VzdGluZyBhIHdlYWsgcmVsYXRpb25zaGlwIHdpdGhvdXQgbXVsdGljb2xsaW5lYXJpdHkuICAKClRoZXJlIGlzIG5vIHNldmVyZSBtdWx0aWNvbGxpbmVhcml0eSBhbW9uZyB0aGUgcHJlZGljdG9ycywgc3VwcG9ydGluZyB0aGUgYXNzdW1wdGlvbnMgb2YgT0xTIHJlZ3Jlc3Npb24uIEhvd2V2ZXIsIGlmIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXggaGFkIHNob3duIGhpZ2ggY29ycmVsYXRpb25zIChcXCh8cnwgXGdlcSAwLjdcXCkpLCB3ZSBjb3VsZCBmdXJ0aGVyIGNvbmZpcm0gdGhlIHNldmVyaXR5IG9mIG11bHRpY29sbGluZWFyaXR5IHVzaW5nIHRoZSAqKlZhcmlhbmNlIEluZmxhdGlvbiBGYWN0b3IgKFZJRikqKiAoKipWSUYgPCA1KiogaW5kaWNhdGVzIGxvdyBtdWx0aWNvbGxpbmVhcml0eSBhbmQgaXMgZ2VuZXJhbGx5IGFjY2VwdGFibGUsIHdoaWxlICoqVklGIFwoXGdlcVwpIDUqKiBzdWdnZXN0cyBtb2RlcmF0ZSB0byBoaWdoIG11bHRpY29sbGluZWFyaXR5IHRoYXQgbWF5IHJlcXVpcmUgYXR0ZW50aW9uLiBJZiAqKlZJRiBcKFxnZXFcKSAxMCoqLCBzZXZlcmUgbXVsdGljb2xsaW5lYXJpdHkgaXMgcHJlc2VudCwgbmVjZXNzaXRhdGluZyBjb3JyZWN0aXZlIG1lYXN1cmVzKS4gIAoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CgpjdXN0b21fbGFiZWxzIDwtIGMoCiAgIiUgb2YgSW5kaXZpZHVhbHMgd2l0aCBCYWNoZWxvcuKAmXMgRGVncmVlcyBvciBIaWdoZXIiID0gIlBDVEJBQ0hNT1IiLAogICIlIG9mIFZhY2FudCBIb3VzZXMiID0gIlBDVFZBQ0FOVCIsCiAgIiUgb2YgU2luZ2xlIEhvdXNlIFVuaXRzIiA9ICJQQ1RTSU5HTEVTIiwKICAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiA9ICJMTk5CRUxQT1YxMDAiCikKCnByZWRpY3Rvcl92YXJzIDwtIGRhdGFbLCBjKCJQQ1RWQUNBTlQiLCAiUENUU0lOR0xFUyIsICJQQ1RCQUNITU9SIiwgIkxOTkJFTFBPVjEwMCIpXQoKY29yX21hdHJpeCA8LSBjb3IocHJlZGljdG9yX3ZhcnMsIHVzZSA9ICJjb21wbGV0ZS5vYnMiLCBtZXRob2QgPSAicGVhcnNvbiIpCgpwcmludChjb3JfbWF0cml4KQpyb3duYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQpjb2xuYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQoKCmdnY29ycnBsb3QoY29yX21hdHJpeCwgCiAgICAgICAgICAgbWV0aG9kID0gInNxdWFyZSIsICAgCiAgICAgICAgICAgdHlwZSA9ICJsb3dlciIsICAgICAgCiAgICAgICAgICAgbGFiID0gVFJVRSwgICAgICAgCiAgICAgICAgICAgbGFiX3NpemUgPSAzLCAgICAgIAogICAgICAgICAgIGNvbG9ycyA9IGMoIiNkNzMwMjciLCAid2hpdGUiLCAiIzFhOTg1MCIpKSsKICAgIGxhYnModGl0bGUgPSAiQ29ycmVsYXRpb24gTWF0cml4IGZvciBhbGwgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICAgIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLCAKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKYGBgCgojIyBSZWdyZXNzaW9uIFJlc3VsdHMKCiMjIyBQYXJhbWV0ZXIgRXN0aW1hdGlvbnMKCkZvdXIgaW5kZXBlbmRlbnQgdmFyaWFibGVzIHdlcmUgaW5jbHVkZWQgaW4gdGhlIG11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWwgdG8gcHJlZGljdCB0aGUgbG9nLXRyYW5zZm9ybWVkIG1lZGlhbiBob3VzZSB2YWx1ZSAoYExOTUVESFZBTGApIGluIFBoaWxhZGVscGhpYSBhdCBjZW5zdXMgYmxvY2sgZ3JvdXAgbGV2ZWwsIGluY2x1ZGluZyB0aGUgcHJvcG9ydGlvbiBvZiB2YWNhbnQgaG91c2luZyB1bml0cyAoYFBDVFZBQ0FOVGApLCB0aGUgcHJvcG9ydGlvbiBvZiBzaW5nbGUtZmFtaWx5IGhvdXNpbmcgdW5pdHMgKGBQQ1RTSU5HTEVTYCksIHRoZSBwcm9wb3J0aW9uIG9mIHJlc2lkZW50cyB3aXRoIGEgYmFjaGVsb3IncyBkZWdyZWUgb3IgaGlnaGVyIChgUENUQkFDSE1PUmApLCBhbmQgdGhlIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBiZWxvdyB0aGUgcG92ZXJ0eSBsaW5lIChgTE5OQkVMUE9WMTAwYCkuIFRoZSByZWdyZXNzaW9uIHJlc3VsdHMgYXJlIHByZXNlbnRlZCBiZWxvdzoKCmBgYHtyIHJlZ3Jlc3Npb259CmZpdCA8LSBsbShMTk1FREhWQUwgfiBQQ1RWQUNBTlQgKyBQQ1RTSU5HTEVTICsgUENUQkFDSE1PUiArIExOTkJFTFBPVjEwMCwgZGF0YT1kYXRhKQpzdW1tYXJ5KGZpdCkKYGBgClRoZSByZWdyZXNzaW9uIG91dHB1dCB0ZWxscyB1cyB0aGF0IHRoZSBtZWRpYW4gaG91c2luZyB2YWx1ZXMgYXJlIGhpZ2hseSBzaWduaWZpY2FudCBjb3JyZWxhdGVkIHdpdGggdGhlIHByb3BvcnRpb24gb2YgdmFjYW50IGhvdXNpbmcgdW5pdHMoYFBDVFZBTlRgKSwgdGhlIHByb3BvcnRpb24gb2Ygc2luZ2xlLWZhbWlseSBob3VzaW5nIHVuaXRzKGBQQ1RTSU5HTEVTYCksIHRoZSBwcm9wb3J0aW9uIG9mIHJlc2lkZW50cyB3aXRoIGEgYmFjaGVsb3IncyBkZWdyZWUgb3IgaGlnaGVyIChgUENUQkFDSE1PUmApLCBhbmQgdGhlIGxvZy10cmFuc2Zvcm1lZCBudW1iZXIgb2YgaG91c2Vob2xkcyBsaXZpbmcgYmVsb3cgdGhlIHBvdmVydHkgbGluZSAoYExOTkJFTFBPVmApLCB3aXRoICRwLXZhbHVlPDAuMDAwMSQgZm9yIGFsbCBmb3VyIHByZWRpY3RvcnMuIAoKQXMgdGhlIHByb3BvcnRpb25zIG9mIHZhY2FudCBob3VzaW5nIHVuaXRzIChgUENUVkFOVGApIGdvZXMgdXAgYnkgMSB1bml0ICgxJSksIHRoZSBtZWRpYW4gaG91c2UgdmFsdWUgZ29lcyBkb3duIGJ5IGFwcHJveGltYXRlbHkgMS45MTUlLCB3aXRoIGhvbGRpbmcgYWxsIG90aGVyIHRocmVlIHByZWRpY3RvcnMgY29uc3RhbnQuIEluIGFkZGl0aW9uLCB0aGUgcmVzcGVjdGl2ZSAkcC12YWx1ZSQgZm9yICRcYmV0YV8xJCBpcyBsZXNzIHRoYW4gMC4wMDAxLCBpbmRpY2F0aW5nIHRoYXQgaWYgdGhlcmUgaXMgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gYFBDVFZBTlRgIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChpLmUuLCBpZiB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgXCggXGJldGFfMSA9IDAgXCkgaXMgIHRydWUpLCB0aGVuIHRoZSBwcm9iYWJpbGl0eSBvZiBnZXR0aW5nIGEgXCggXGJldGFfMSBcKSBjb2VmZmljaWVudCBlc3RpbWF0ZSBvZiAtMC4wMTkxNTY5IGlzIGxlc3MgdGhhbiAwLjAwMDEuIFdlIGNhbiBzYWZlbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGJldGFfMSA9IDAkIGZvciAkSF9hOiBcYmV0YV8xIFxuZXEgMCQuIAoKJCQoZV57XGJldGF9IC0gMSkgXHRpbWVzIDEwMFwlID0gKGVeey0wLjAxOTE1Njl9IC0gMSkgXHRpbWVzIDEwMFwlIFxhcHByb3ggLTEuOTE1XCUgJCQKCgpTaW1pbGFybHksIGFzIHRoZSBwcm9wb3J0aW9uIG9mIHNpbmdsZS1mYW1pbHkgaG91c2luZyB1bml0cyAoYFBDVFNJTkdMRVNgKSBnb2VzIHVwIGJ5IDEgdW5pdCAoMSUpLCB0aGUgbWVkaWFuIGhvdXNlIHZhbHVlIGdvZXMgdXAgYnkgYXBwcm94aW1hdGVseSAwLjI5OCUsIHdpdGggaG9sZGluZyBhbGwgb3RoZXIgdGhyZWUgcHJlZGljdG9ycyBjb25zdGFudC4gVGhlICRwLXZhbHVlJCBmb3IgJFxiZXRhXzIkIGlzIGxlc3MgdGhhbiAwLjAwMDEsIGluZGljYXRpbmcgdGhhdCBpZiB0aGVyZSBpcyBubyByZWxhdGlvbnNoaXAgYmV0d2VlbiBgUENUU0lOR0xFU2AgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKGkuZS4sIGlmIHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCBcKCBcYmV0YV8yID0gMCBcKSBpcyAgdHJ1ZSksIHRoZW4gdGhlIHByb2JhYmlsaXR5IG9mIGdldHRpbmcgYSBcKCBcYmV0YV8yIFwpIGNvZWZmaWNpZW50IGVzdGltYXRlIG9mIDAuMDAyOTc2OSBpcyBsZXNzIHRoYW4gMC4wMDAxLiBXZSBjYW4gYWxzbyBzYWZlbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGJldGFfMiA9IDAkIGZvciAkSF9hOiBcYmV0YV8yIFxuZXEgMCQuCgokJChlXntcYmV0YX0gLSAxKSBcdGltZXMgMTAwXCUgPSAoZV57LTAuMDAyOTc2OX0gLSAxKSBcdGltZXMgMTAwXCUgXGFwcHJveCAwLjI5OFwlICQkCgpGdXJ0aGVybW9yZSwgYXMgdGhlIHByb3BvcnRpb24gb2YgcmVzaWRlbnRzIHdpdGggYSBiYWNoZWxvcidzIGRlZ3JlZSBvciBoaWdoZXIgKGBQQ1RCQUNITU9SYCkgZ29lcyB1cCBieSAxIHVuaXQgKDElKSwgdGhlIG1lZGlhbiBob3VzZSB2YWx1ZSBnb2VzIHVwIGJ5IGFwcHJveGltYXRlbHkgMi4wOSUsIHdpdGggaG9sZGluZyBhbGwgb3RoZXIgdGhyZWUgcHJlZGljdG9ycyBjb25zdGFudC4gU2ltaWxhciB0byAkXGJldGFfMiQsIHRoZSAkcC12YWx1ZSQgZm9yICRcYmV0YV8zJCBpcyBsZXNzIHRoYW4gMC4wMDAxLCBpbmRpY2F0aW5nIHRoYXQgaWYgdGhlcmUgaXMgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gYFBDVEJBQ0hNT1JgIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChpLmUuLCBpZiB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgXCggXGJldGFfMyA9IDAgXCkgaXMgIHRydWUsIHRoZW4gdGhlIHByb2JhYmlsaXR5IG9mIGdldHRpbmcgYSBcKCBcYmV0YV8zIFwpIGNvZWZmaWNpZW50IGVzdGltYXRlIG9mIDAuMDIwOTA5OCBpcyBsZXNzIHRoYW4gMC4wMDAxLiBXZSBjYW4gYWxzbyBzYWZlbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGJldGFfMyA9IDAkIGZvciAkSF9hOiBcYmV0YV8zIFxuZXEgMCQuCgokJChlXntcYmV0YX0gLSAxKSBcdGltZXMgMTAwXCUgPSAoZV57MC4wMjA5MDk4fSAtIDEpIFx0aW1lcyAxMDBcJSBcYXBwcm94IDIuMDlcJSAkJAoKTGFzdGx5LCBhcyAxIHBlcmNlbnQgaW5jcmVhc2UgaW4gdGhlIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBiZWxvdyB0aGUgcG92ZXJ0eSBsaW5lLCB0aGUgbWVkaWFuIGhvdXNlIHZhbHVlIGdvZXMgZG93biBieSBhcHByb3hpbWF0ZWx5IDAuMDc4JSAsIHdpdGggaG9sZGluZyBhbGwgb3RoZXIgdGhyZWUgcHJlZGljdG9ycyBjb25zdGFudC4gVGhlICRwLXZhbHVlJCBmb3IgJFxiZXRhXzQkIGlzIGFsc28gbGVzcyB0aGFuIDAuMDAwMSAgaW5kaWNhdGluZyB0aGF0IGlmIHRoZXJlIGlzIG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG51bWJlciBvZiBob3VzZWhvbGRzIGJlbG93IHBvdmVydHkgbGluZSBhbmQgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAoaS5lLiwgaWYgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IFwoIFxiZXRhXzQgPSAwIFwpIGlzICB0cnVlKSwgdGhlbiB0aGUgcHJvYmFiaWxpdHkgb2YgZ2V0dGluZyBhIFwoIFxiZXRhXzQgXCkgY29lZmZpY2llbnQgZXN0aW1hdGUgb2YgLTAuMDc4OTA1NCBpcyBsZXNzIHRoYW4gMC4wMDAxLiBBcyBzdGF0ZWQgYmVmb3JlLCB3ZSBjYW4gYWxzbyBzYWZlbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGJldGFfNCA9IDAkIGZvciAkSF9hOiBcYmV0YV80IFxuZXEgMCQuCgokJCgxLjAxXntcYmV0YX0gLSAxKSBcdGltZXMgMTAwXCUgPSAoMS4wMV57LTAuMDc4OTA1NH0gLSAxKSBcdGltZXMgMTAwXCUgIFxhcHByb3ggLTAuMDc4XCUkJAoKIyMjIE1vZGVsIEZpdAoKYGBge3IgcmVncmVzc2lvbjF9CmZpdCA8LSBsbShMTk1FREhWQUwgfiBQQ1RWQUNBTlQgKyBQQ1RTSU5HTEVTICsgUENUQkFDSE1PUiArIExOTkJFTFBPVjEwMCwgZGF0YT1kYXRhKQpzdW1tYXJ5KGZpdCkKYGBgCkZpcnN0LCB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIG1vZGVsIHNob3cgYSByZWFzb25hYmxlIGRpc3RyaWJ1dGlvbiBvZiBlcnJvcnMsIHdpdGggYSBtZWRpYW4gcmVzaWR1YWwgb2YgMC4wMzgyMiwgYSBtaW5pbXVtIHZhbHVlIG9mIC0yLjI2LCBhIGZpcnN0IHF1YXJ0aWxlIG9mIC0wLjIwLCBhbmQgYSB0aGlyZCBxdWFydGlsZSBvZiAwLjIyLCBhbmQgYSBtYXhpbXVtIHZhbHVlIG9mIDIuMjQuIFRoaXMgZGlzdHJpYnV0aW9uIHNob3dzIHRoYXQgdGhlIG1vZGVsIGNhcHR1cmVzIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIHdlbGwgKGxvZ2dlZCB0cmFuc2Zvcm1lZCBtZWRpYW4gaG9tZSB2YWx1ZSksIGFsdGhvdWdoIHNvbWUgb2YgdGhlIHJlc2lkdWFscyBhcmUgbGFyZ2VyIHRoYW4gMi41IHN0YW5kYXJkIGRldmlhdGlvbnMgZnJvbSB0aGUgbWVhbiwgd2hpY2ggYXJlIHRoZSBvdXRsaWVycy4KCk1vcmVvdmVyLCB0aGUgbW9kZWwgaGFzIGEgbXVsdGlwbGUgXChSXjJcKSB2YWx1ZSBvZiAwLjY2MjMgYW5kIGFuIGFkanVzdGVkIFwoUl4yXCkgdmFsdWUgb2YgMC42NjE1LCBpbmRpY2F0aW5nIHRoYXQgYXBwcm94aW1hdGVseSA2NiUgb2YgdGhlIHZhcmlhbmNlIGluIGBMTk1FREhWQUxgIGlzIGV4cGxhaW5lZCBieSB0aGUgcHJlZGljdG9ycy4gIFRoZSAkRi1zdGF0aXN0aWMkIG9mIDg0MC4wIHdpdGggYSAkcC12YWx1ZSQgbGVzcyB0aGFuIDAuMDAwMSwgaW5kaWNhdGluZyB0aGF0IHRoZSBtb2RlbCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgoKYGBge3J9CmFub3ZhX3RhYmxlIDwtIGFub3ZhKGZpdCkKYW5vdmFfdGFibGUKYGBgCgpUaGUgQW5hbHlzaXMgb2YgVmFyaWFuY2UgKEFOT1ZBKSB0YWJsZSBzaG93cyBhZGRpdGlvbmFsIGluc2lnaHQgaW50byB0aGUgc2lnbmlmaWNhbmNlIG9mIGVhY2ggcHJlZGljdG9yIGluIGV4cGxhaW5pbmcgdGhlIHZhcmlhdGlvbiBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChgTE5WTUVESFZBTGApLiBGb3IgcHJvcG9ydGlvbiBvZiB2YWNhbnQgaG91c2luZyB1bml0cyAoYFBDVFZBQ0FOVGApLCB0aGUgc3VtIG9mIHNxdWFyZXMgaXMgMTgwLjM5MiwgaW5kaWNhdGluZyB0aGF0IHRob3NlIGFtb3VudCBvZiB2YXJpYXRpb24gaW4gYExOVk1FREhWQUxgIHRoYXQgY2FuIGJlIGF0dHJpYnV0ZWQgdG8gY2hhbmdlcyBpbiBgUENUVkFDQU5UYC4gQSBoaWdoZXIgc3VtIG9mIHNxdWFyZXMgaW5kaWNhdGVzIGEgbWhpZ2hlciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgcHJlZGljdG9yIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBUaGUgc3VtIG9mIHNxdWFyZXMgZm9yIHRoZSBwZXJjZW50YWdlIG9mIHJlc2lkZW50cyB3aXRoIGEgYmFjaGVsb3IncyBkZWdyZWUgb3IgaGlnaGVyIChgUENUQkFDSE1PUmApIGV4cGxhaW5zIHRoZSBoaWdoZXN0IHBvcnRpb24gb2YgdGhlIHZhcmlhbmNlIGluIGBMTlZNRURIVkFMYC4gSW4gY29udHJhc3QsIHRoZSBzdW0gb2Ygc3F1YXJlcyBmb3IgdGhlIGxvZy10cmFuc2Zvcm1lZCBudW1iZXIgb2YgaG91c2Vob2xkcyBsaXZpbmcgYmVsb3cgdGhlIHBvdmVydHkgbGluZSAoYExOTkJFTFBPVjEwMGApIGV4cGxhaW5zIHRoZSBsZWFzdCBhbW91bnQgb2YgdmFyaWFuY2UgaW4gYExOVk1FREhWQUxgLCB3aXRoIG9ubHkgMTEuNjkuIAoKVGhlIHRvdGFsIHN1bSBvZiBzcXVhcmVzLCB3aGljaCByZXByZXNlbnRzIHRoZSB0b3RhbCB2YXJpYW5jZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChgTE5WTUVESFZBTGApLCBpcyAyMzAuMzQsIHdpdGggYSBtZWFuIHNxdWFyZSBlcnJvciBvZiAwLjEzNC4gT3ZlcmFsbCwgdGhlIEFOT1ZBIHRhYmxlIHByb3ZpZGVzIGEgY29tcHJlaGVuc2l2ZSBvdmVydmlldyBvZiB0aGUgc2lnbmlmaWNhbmNlIG9mIGVhY2ggcHJlZGljdG9yIGluIHRoZSBtb2RlbCBhbmQgdGhlIHByb3BvcnRpb24gb2YgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IGVhY2ggcHJlZGljdG9yLiBJdCBjb25maXJtcyB0aGF0IGFsbCBmb3VyIHByZWRpY3RvcnMgY29udHJpYnV0ZSBzaWduaWZpY2FudGx5IHRvIGV4cGxhaW5pbmcgdGhlIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIFRoZXNlIGZpbmRpbmdzIHByb3ZpZGUgc3Ryb25nIGV2aWRlbmNlIG9mIHRoZSByb2J1c3RuZXNzIG9mIHRoZSBtb2RlbCBhbmQgdGhlIHJlbGV2YW5jZSBvZiBuZWlnaGJvdXJob29kIGNoYXJhY3RlcmlzdGljcyBpbiBwcmVkaWN0aW5nIGhvdXNpbmcgdmFsdWVzLgoKCiMjIFJlZ3Jlc3Npb24gQXNzdW1wdGlvbnMgQ2hlY2sKCkluIHRoaXMgc2VjdGlvbiwgd2UgY29uZHVjdGVkIHZhcmlldHkgb2YgYW5hbHlzaXMgdG8gY2hlY2sgaWYgdGhlIGFzc3VtcHRpb24gb2YgdGhlIGxpbmVhciByZWdyZXNzaW9uIHdlcmUgbWV0LiBJbiB0aGUgZWFybGllciBzZWN0aW9uLCB3ZSBhbHJlYWR5IGNoZWNrZWQgdGhlIHZhcmlhYmxlIGRpc3RyaWJ1dGlvbiBhbmQgbXVsdGljb2xsaW5lYXJpdHkuIEhlcmUsIHdlIHdpbGwgY2hlY2sgZm9sbG93aW5nIGFzc3VtcHRpb246CgotIExpbmVhcml0eQotIE5vcm1hbGl0eSBvZiBSZXNpZHVhbHMKLSBIb21vc2NlZGFzdGljaXR5CgojIyMgTGluZWFyaXR5CgpUbyBmdXJ0aGVyIGV4YW1pbmUgdGhlIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCB0aGUgcHJlZGljdG9ycywgd2UgY3JlYXRlIGZvdXIgc2NhdHRlciBwbG90cywgd2hlcmUgdGhlIHgtYXhpcyByZXByZXNlbnRzIGVhY2ggcHJlZGljdG9yIGFuZCB0aGUgeS1heGlzIHJlcHJlc2VudHMgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSwgKkxvZyBUcmFuc2Zvcm1lZCBNZWRpYW4gSG91c2UgVmFsdWUqLiAKCmBgYHtyIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTksIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxvbmdlcjwtZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBDVEJBQ0hNT1IiLCAiTE5OQkVMUE9WMTAwIiwgIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXIsYWVzKHggPSBWYWx1ZSwgeSA9IExOTUVESFZBTCkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIiwgc2l6ZT0gMC40KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3IgPSAicmVkIiwgc2UgPSBGQUxTRSkgKyAKICBmYWNldF93cmFwKH4gVmFyaWFibGUsIHNjYWxlcyA9ICJmcmVlIiwgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihjKAogICAgIlBDVEJBQ0hNT1IiID0gIiUgd2l0aCBCYWNoZWxvcuKAmXMgRGVncmVlcyBvciBIaWdoZXIiLAogICAgIkxOTkJFTFBPVjEwMCIgPSAiTG9nZ2VkIEhvdXNlaG9sZHMgTGl2aW5nIGluIFBvdmVydHkiLAogICAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAgICJQQ1RTSU5HTEVTIiA9ICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkgKwogIGxhYnModGl0bGUgPSAiU2NhdHRlciBQbG90cyBvZiBEZXBlbmRlbnQgVmFyaWFibGUgdnMuIFByZWRpY3RvcnMiLCAKICAgICAgIHggPSAiUHJlZGljdG9yIFZhbHVlIiwgCiAgICAgICB5ID0gIkxvZyBvZiBNZWRpYW4gSG91c2UgVmFsdWUiKQpgYGAKCkZyb20gdGhlIHBsb3RzLCB3ZSBvYnNlcnZlIHRoZSBmb2xsb3dpbmcgdHJlbmRzOiAgCgotICoqTG9nZ2VkIEhvdXNlaG9sZHMgTGl2aW5nIGluIFBvdmVydHkqKiBzaG93cyBhIG5lZ2F0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAgd2l0aCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBBcyB0aGUgcGVyY2VudGFnZSBvZiBob3VzZWhvbGRzIGxpdmluZyBpbiBwb3ZlcnR5IGluY3JlYXNlcywgdGhlICpMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlKiBkZWNyZWFzZXMuIFRoaXMgaXMgcmVmbGVjdGVkIGluIGl0cyBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBcXCg8IDBcXCkuIEhvd2V2ZXIsIHRoZSBhc3NvY2lhdGlvbiBpcyBub3Qgc3RyaWN0bHkgbGluZWFyLiBJbiB0aGUgZ3JhcGgsIHRoZSBwb2ludHMgYXJlIG1vcmUgc2NhdHRlcmVkIHdpZGVseSwgcGFydGljdWxhciBhdCBsb3dlciBsZXZlbCBvZiBwb3ZlcnR5LCB3aGVyZSBob3VzaW5nIHZhbHVlcyB2YXJ5IHNpZ25pZmljYW50bHkuIFRoaXMgaW5kaWNhdGUgd2hpbGUgcG92ZXJ0eSBsZXZlbHMgaGF2ZSBhIG5lZ2F0aXZlIGltcGFjdCBvbiBob3VzaW5nIHZhbHVlcywgdGhlIGVmZmVjdCBpcyBub3QgdW5pZm9ybSBhY3Jvc3MgYWxsIGJsb2NrIGdyb3Vwcy4gVGhlcmUgaXMgYSBzdWJzdGFudGlhbCB2YXJpYXRpb24gaW4gaG91c2luZyB2YWx1ZXMgZXZlbiBhdCBzaW1pbGFyIHBvdmVydHkgbGV2ZWxzLCB3aGljaCBzdWdnZXN0cyB0aGF0IG90aGVyIGZhY3RvcnMgbWF5IGFsc28gYmUgaW5mbHVlbmNpbmcgaG91c2luZyB2YWx1ZXMuCgotICoqJSB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlcioqIGV4aGliaXRzIGEgcG9zaXRpdmUgbGluZWFyIHJlbGF0aW9uc2hpcCB3aXRoIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIFdoZW4gdGhlIHBlcmNlbnRhZ2Ugb2YgaW5kaXZpZHVhbHMgd2l0aCBhIGJhY2hlbG9yJ3MgZGVncmVlIG9yIGhpZ2hlciBpbmNyZWFzZXMsIHRoZSAqTG9nIFRyYW5zZm9ybWVkIE1lZGlhbiBIb3VzZSBWYWx1ZSogYWxzbyByaXNlcywgd2l0aCBhIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IFxcKD4gMFxcKS4gIFRoZSBwb2ludHMgb24gdGhlIGdyYXBoIGZvcm0gYSB0aWdodCBiYW5kIGFsb25nIHRoZSB0cmVuZCBsaW5lLCBpbmRpY2F0aW5nIHRoYXQgaGlnaGVyIGVkdWNhdGlvbiBsZXZlbHMgd2l0aGluIGEgbmVpZ2hib3Job29kIGlzIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggaGlnaGVyIGhvdXNpbmcgdmFsdWVzLiBUaGUgY29uc2lzdGVudCB1cHdhcmQgdHJlbmQgc3VnZ2VzdCB0aGF0IGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgaXMgYSBrZXkgZHJpdmVyIG9mIGhvdXNpbmcgcHJpY2VzLCBhbmQgYSBjbGVhciBsaW5lYXIgdHJlbmQgaW1wbGllcyB0aGF0IHRoaXMgdmFyaWFibGUgaXMgc3VpdGFibGUgZm9yIHRoaXMgbGluZWFyIHJlZ3Jlc3Npb24gYW5hbHlzaXMuCgotICoqJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMqKiBoYXMgYSB3ZWFrZXIgYnV0IHN0aWxsIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCB3aXRoIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIFdoaWxlIHRoZSB0cmVuZCBpcyBub3Qgb2J2aW91cywgYXJlYXMgd2l0aCBhIGhpZ2hlciBwZXJjZW50YWdlIG9mIHNpbmdsZS1ob3VzZSB1bml0cyB0ZW5kIHRvIGhhdmUgaGlnaGVyICpMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlcyosIGVzcGVjaWFsbHkgd2hlbiB0aGUgcGVyY2VudGFnZSBpcyBzdWZmaWNpZW50bHkgbGFyZ2UuIFRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBpcyBcXCg+IDBcXCkuIFRoZSBzY2F0dGVyIHBvaW50cyBzaG93cyBzaWduaWZpY2FudCB2YXJpYWJpbGl0eSBpbiBob3VzaW5nIHZhbHVlcyBhdCB2YXJpb3VzIGxldmVscyBvZiBzaW5nbGUtaG91c2UgdW5pdHMsIHdpdGggc29tZSBibG9jayBncm91cHMgaGF2aW5nIGhpZ2ggaG91c2luZyB2YWx1ZXMgZGVzcGl0ZSBhIGxvdyBwZXJjZW50YWdlIG9mIHNpbmdsZS1ob3VzZSB1bml0cy4gVGhpcyB2YXJpYWJpbGl0eSBzdWdnZXN0cyB0aGF0IHdoaWxlIHRoZXJlIGlzIGEgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gc2luZ2xlLWhvdXNlIHVuaXRzIGFuZCBob3VzaW5nIHZhbHVlcywgb3RoZXIgZmFjdG9ycyBtYXkgYWxzbyBiZSBpbmZsdWVuY2luZyBob3VzaW5nIHZhbHVlcyBhdCB0aGUgc2FtZSB0aW1lLiAKCi0gKiolIG9mIFZhY2FudCBIb3VzZXMqKiBoYXMgYSBnZW5lcmFsIG5lZ2F0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAgd2l0aCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBBcyB0aGUgcGVyY2VudGFnZSBvZiB2YWNhbnQgaG91c2VzIGluY3JlYXNlcywgdGhlICpMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlKiBkZWNyZWFzZXMsIHdpdGggYSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBcXCg8IDBcXCkuIEhvd2V2ZXIsIGluIHRoZSBncmFwaCwgaXQgcmV2ZWFscyBhIG1vcmUgY29tcGxleCByZWxhdGlvbnNoaXAgd2l0aCBzaWduaWZpY2FudCB2YXJpYXRpb24gaW4gaG91c2luZyB2YWx1ZXMgYWNyb3NzIGRpZmZlcmVudCB2YWNhbmN5IHJhdGVzLiBUaGVyZSBhcmUgY2x1c3RlcnMgb2YgYmxvY2sgZ3JvdXBzIHdpdGggaGlnaCBob3VzaW5nIHZhbHVlcyBhbmQgbG93IHZhY2FuY3kgcmF0ZXMsIGluZGljYXRpbmcgdGhhdCB0aGUgcmVsYXRpb25zaGlwIGlzIG5vdCBzdHJpY3RseSBsaW5lYXIuSW4gdGhlIG1pZGRsZSBhbmQgbG93ZXIgcmFuZ2VzIG9mIHZhY2FuY3kgcmF0ZXMsIHRoZSBkZWNsaW5lIGluIGhvdXNpbmcgdmFsdWVzIGJlY29tZXMgbGVzcyBwcm9ub3VuY2VkLiBUaGlzIHN1Z2dlc3RzIHRoYXQgd2hpbGUgdmFjYW50IGhvdXNpbmcgaXMgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIHByb3BlcnR5IHZhbHVlcywgdGhlIGltcGFjdCBkaW1pbmlzaGVzIG9yIGJlY29tZXMgbGVzcyBwcmVkaWN0YWJsZSBhcyB0aGUgdmFjYW5jeSByYXRlIGNoYW5nZXMuICAKCkluIHN1bW1hcnksIHRoZSBzY2F0dGVycGxvdCBzaG93cyB0aGF0IHdoaWxlIHRoZSBQQ1RCQUNITU9SIGFuZCBMTk1FREhWQUwgaGF2ZSBhIGNsZWFyIGxpbmVhciByZWxhdGlvbnNoaXAsIHRoZSBvdGhlciBwcmVkaWN0b3JzIGhhdmUgbW9yZSBjb21wbGV4IG5vbi1saW5lYXIgcmVsYXRpb25zaGlwcyB3aXRoIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIFRoaXMgc3VnZ2VzdHMgdGhhdCB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgbWF5IG5vdCBmdWxseSBjYXB0dXJlIHRoZSBjb21wbGV4aXR5IG9mIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIHByZWRpY3RvcnMgYW5kIG1lZGlhbiBob3VzZSB2YWx1ZXMuCgoKIyMjIE5vcm1hbGl0eSBvZiBSZXNpZHVhbHMKCk5leHQsIHdlIGV4YW1pbmUgdGhlIG5vcm1hbGl0eSBvZiByZXNpZHVhbHMgb2YgdGhlIHJlZ3Jlc3Npb24gbW9kZWwuIFRoZSBoaXN0b2dyYW0gb2Ygc3RhbmRhcmRpemVkIHJlc2lkdWFscyBwcm92aWRlcyBhIGRldGFpbCB2aWV3IG9mIHRoZSAgb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIE9MUyBtb2RlbCwgc2hvd2luZyBiZWxvdzoKCmBgYHtyLCBpbmNsdWRlPSBGQUxTRX0KZml0dGVkX3ZhbHVlcyA8LSBmaXR0ZWQoZml0KQpyZXNpZHVhbHNfdmFsdWVzIDwtIHJlc2lkdWFscyhmaXQpCnN0YW5kYXJkaXplZF9yZXNpZHVhbHMgPC0gcnN0YW5kYXJkKGZpdCkKCmRhdGEgPC0gZGF0YSAlPiUKICBtdXRhdGUoCiAgICBGaXR0ZWQgPSBmaXR0ZWRfdmFsdWVzLAogICAgUmVzaWR1YWxzID0gcmVzaWR1YWxzX3ZhbHVlcywKICAgIFN0YW5kYXJkaXplZF9SZXNpZHVhbHMgPSBzdGFuZGFyZGl6ZWRfcmVzaWR1YWxzKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBTdGFuZGFyZGl6ZWRfUmVzaWR1YWxzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgZmlsbCA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIiwgCiAgICAgICB4ID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLCAKICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX21pbmltYWwoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhLCBhZXMoeCA9IEZpdHRlZCwgeSA9IFN0YW5kYXJkaXplZF9SZXNpZHVhbHMpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibGFjayIsIHNpemU9IDAuNCkgKyAgICAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiKSArICAKICBsYWJzKAogICAgdGl0bGUgPSAiU2NhdHRlciBQbG90IG9mIFN0YW5kYXJkaXplZCBSZXNpZHVhbHMgdnMgRml0dGVkIFZhbHVlcyIsCiAgICB4ID0gIlByZWRpY3RlZCBWYWx1ZXMiLAogICAgeSA9ICJTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD05LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpqb2luPC0gZGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KFBPTFlfSUQsIFN0YW5kYXJkaXplZF9SZXNpZHVhbHMpCgpzaGFwZSA8LSBzaGFwZSAlPiUKICBsZWZ0X2pvaW4oam9pbiwgYnkgPSBjKCJQT0xZX0lEIiA9ICJQT0xZX0lEIikpCgpnZ3Bsb3Qoc2hhcGUpKwogIGdlb21fc2YoYWVzKGZpbGwgPSBTdGFuZGFyZGl6ZWRfUmVzaWR1YWxzKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3JzID0gYygiI2ZmZjBmMyIsICIjYTQxMzNjIiksIAogICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiU3RkIFJlc2lkdWFscyIsIAogICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IikgKyAgIyBDaG9vc2UgYSBjb2xvciBwYWxldHRlLCBpbnZlcnQgZGlyZWN0aW9uIGlmIG5lZWRlZAogIGxhYnModGl0bGUgPSAiQ2hvcm9wbGV0aCBNYXAgb2YgU3RhbmRhcmRpemVkIFJlc2lkdWFscyIpICsKICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleSIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuOCkpCgpgYGAKCgoKCiMjIEFkZGl0aW9uYWwgQW5hbHlzaXMKCmBgYHtyfQpzdGVwd2lzZV9tb2RlbCA8LSAgc3RlcEFJQyhmaXQsIGRpcmVjdGlvbiA9ICJib3RoIikKc3RlcHdpc2VfbW9kZWwkYW5vdmEKYGBgCgpgYGB7ciBjcm9zcyB2YWxpZGF0aW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nID0gRkFMU0V9CgpsbSA8LSAgdHJhaW5Db250cm9sKG1ldGhvZCA9ICJjdiIsIG51bWJlciA9IDUpCgpjdmxtX21vZGVsIDwtIHRyYWluKExOTUVESFZBTCB+IFBDVFZBQ0FOVCArIFBDVFNJTkdMRVMgKyBQQ1RCQUNITU9SICsgTE5OQkVMUE9WMTAwLCBkYXRhPWRhdGEsIG1ldGhvZCA9ICJsbSIsIHRyQ29udHJvbCA9IGxtKQoKcHJpbnQoY3ZsbV9tb2RlbCkKCmBgYAoKCmBgYHtyIHJlZHVjZSBjdiBtb2RlbCxtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKY3ZsbV9tb2RlbF9yZWR1Y2VkID0gdHJhaW4oTE5NRURIVkFMIH4gUENUVkFDQU5UICsgTUVESEhJTkMsIGRhdGEgPSBkYXRhLCBtZXRob2QgPSAibG0iLCB0ckNvbnRyb2wgPSBsbSkKCnByaW50KGN2bG1fbW9kZWxfcmVkdWNlZCkKYGBgCgoKIyBEaXNjdXNzaW9uCgpPdXIgcmVncmVzc2lvbiBhbmFseXNpcyBvZiBQaGlsYWRlbHBoaWHigJlzIGNlbnN1cyBibG9jayBncm91cCBkYXRhIGNsZWFybHkgc2hvd3MgaG93IG5laWdoYm9yaG9vZCBjaGFyYWN0ZXJpc3RpY3MgYWZmZWN0IGhvdXNpbmcgdmFsdWVzLiBPdXIgbW9kZWwgZXhwbGFpbnMgYWJvdXQgNjYlIG9mIHRoZSB2YXJpYXRpb24gaW4gdGhlIGxvZy10cmFuc2Zvcm1lZCBtZWRpYW4gaG91c2UgdmFsdWUgKExOTUVESFZBTCkuIFRoaXMgaW5kaWNhdGVzIHRoYXQgZmFjdG9ycyBzdWNoIGFzIHRoZSBwZXJjZW50YWdlIG9mIHZhY2FudCBob3VzZXMgKFBDVFZBQ0FOVCksIHRoZSBwZXJjZW50YWdlIG9mIHNpbmdsZS1mYW1pbHkgaG9tZXMgKFBDVFNJTkdMRVMpLCB0aGUgcGVyY2VudGFnZSBvZiByZXNpZGVudHMgd2l0aCBhdCBsZWFzdCBhIGJhY2hlbG9y4oCZcyBkZWdyZWUgKFBDVEJBQ0hNT1IpLCBhbmQgdGhlIGxvZy10cmFuc2Zvcm1lZCBudW1iZXIgb2YgaG91c2Vob2xkcyBsaXZpbmcgYmVsb3cgdGhlIHBvdmVydHkgbGluZSAoTE5OQkVMUE9WMTAwKSBhcmUgYWxsIGltcG9ydGFudCBpbiBzaGFwaW5nIGhvdXNpbmcgbWFya2V0IG91dGNvbWVzLgoKKipJbnRlcnByZXRpbmcgdGhlIFJlc3VsdHM6KioKCioqTmVlZCB0byByZXdyaXRlKiogV2UgY2Fubm90IGluY2x1ZGUgbG9nLXRyYW5zZm9ybWVkIHZhbHVlIGRpcmVjdGx5IGludG8gdGhlIHJlcG9ydCwgc2VlIHRoZSBhYm92ZSBpbnRlcnByZXQgc2VjdGlvbiBmb3IgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSByZXN1bHRzLgoKKipDaGVja2luZyB0aGUgTW9kZWwgQXNzdW1wdGlvbnM6KioKCioqYikJVGFsayBhYm91dCB0aGUgcXVhbGl0eSBvZiB0aGUgbW9kZWwg4oCTIHRoYXQgaXMsIHN0YXRlIGlmIHRoaXMgaXMgYSBnb29kIG1vZGVsIG92ZXJhbGwgKGUuZy4sIFIyLCBGLXJhdGlvIHRlc3QpLCBhbmQgd2hhdCBvdGhlciBwcmVkaWN0b3JzIHRoYXQgd2UgZGlkbuKAmXQgaW5jbHVkZSBpbiBvdXIgbW9kZWwgbWlnaHQgYmUgYXNzb2NpYXRlZCB3aXRoIG91ciBkZXBlbmRlbnQgdmFyaWFibGUuKioKaS4JTG9va2luZyBhdCB0aGUgc3RlcHdpc2UgcmVncmVzc2lvbiByZXN1bHRzLCBkaWQgdGhlIGZpbmFsIG1vZGVsIGluY2x1ZGUgYWxsIDQgcHJlZGljdG9ycyBvciB3ZXJlIHNvbWUgZHJvcHBlZD8gV2hhdCBkb2VzIHRoYXQgdGVsbCB5b3UgYWJvdXQgdGhlIHF1YWxpdHkgb2YgdGhlIG1vZGVsPyAKaWkuCUxvb2tpbmcgYXQgdGhlIGNyb3NzLXZhbGlkYXRpb24gcmVzdWx0cywgd2FzIHRoZSBSTVNFIGJldHRlciBmb3IgdGhlIDQgcHJlZGljdG9yIG1vZGVsIG9yIHRoZSAyIHByZWRpY3RvciBtb2RlbD8gIAoKCgpUbyB2YWxpZGF0ZSBvdXIgbW9kZWwsIHdlIHBlcmZvcm1lZCBzdGVwd2lzZSByZWdyZXNzaW9uIHVzaW5nIHRoZSBBa2Fpa2UgSW5mb3JtYXRpb24gQ3JpdGVyaW9uIChBSUMpIGFuZCBjb25kdWN0ZWQgNS1mb2xkIGNyb3NzLXZhbGlkYXRpb24uIFRoZSBzdGVwd2lzZSByZWdyZXNzaW9uIGNvbmZpcm1lZCB0aGF0IHRoZSBzZWxlY3RlZCBwcmVkaWN0b3JzIGNvbnRyaWJ1dGUgdG8gYSBzdHJvbmcgbW9kZWwgZml0LCB3aGlsZSB0aGUgY3Jvc3MtdmFsaWRhdGlvbiByZXN1bHRzIHNob3dlZCB0aGF0IHRoZSBmdWxsIG1vZGVsIHdoaWNoIGluY2x1ZGVzIGFsbCB0aGUgZm91ciBwcmVkaWN0b3JzIHBlcmZvcm1zIGJldHRlciB0aGFuIGEgcmVkdWNlZCBtb2RlbCB0aGF0IG9ubHkgaW5jbHVkZXMgdGhlIHBlcmNlbnRhZ2Ugb2YgdmFjYW50IGhvdXNlcyAoUENUVkFDQU5UKSBhbmQgbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUuIFRoZXNlIHJlc3VsdHMgc3RyZW5ndGhlbiBvdXIgY29uZmlkZW5jZSBpbiB0aGUgcHJlZGljdGl2ZSBwb3dlciBhbmQgcm9idXN0bmVzcyBvZiB0aGUgbW9kZWwuCgoKCioqUG9saWN5IEltcGxpY2F0aW9uczogQSBGb2N1cyBvbiBJbmNsdXNpdmUgR3Jvd3RoIGFuZCBTdGFiaWxpdHk6IChvbmUgcGFyYWdyYXBoIG9ubHkpKioKClRoZSBmaW5kaW5ncyBoYXZlIGltcG9ydGFudCBpbXBsaWNhdGlvbnMgZm9yIHVyYmFuIHBvbGljeSwgcGFydGljdWxhcmx5IGluIGVuc3VyaW5nIHRoYXQgc3RyYXRlZ2llcyB0byBpbXByb3ZlIGhvdXNpbmcgbWFya2V0cyBkbyBub3QgbGVhZCB0byBkaXNwbGFjZW1lbnQgb3IgaW5jcmVhc2VkIGhvdXNpbmcgYnVyZGVucyBmb3IgdnVsbmVyYWJsZSBjb21tdW5pdGllcy4gVGhlIHN0cm9uZyBuZWdhdGl2ZSBpbXBhY3Qgb2YgdmFjYW5jeSByYXRlcyAoUENUVkFDQU5UKSBvbiBob3VzaW5nIHZhbHVlcyBzdWdnZXN0cyB0aGF0IHJlZHVjaW5nIGxvbmctdGVybSB2YWNhbmNpZXMgY291bGQgcGxheSBhIHJvbGUgaW4gbmVpZ2hib3Job29kIHN0YWJpbGl6YXRpb24uIEhvd2V2ZXIsIHJhdGhlciB0aGFuIHBvbGljaWVzIHRoYXQgc29sZWx5IGZvY3VzIG9uIGluY3JlYXNpbmcgcHJvcGVydHkgdmFsdWVzLCBpbnRlcnZlbnRpb25zIHNob3VsZCBwcmlvcml0aXplIGVxdWl0YWJsZSBpbnZlc3RtZW50IGxpa2UgcmVoYWJpbGl0YXRpbmcgdmFjYW50IHByb3BlcnRpZXMgZm9yIGFmZm9yZGFibGUgaG91c2luZywgZXhwYW5kaW5nIGNvbW11bml0eSBsYW5kIHRydXN0cywgYW5kIG9mZmVyaW5nIHN1cHBvcnQgZm9yIGxvbmd0aW1lIHJlc2lkZW50cyBhdCByaXNrIG9mIGRpc3BsYWNlbWVudC4KClNpbWlsYXJseSwgdGhlIHN0cm9uZyByZWxhdGlvbnNoaXAgYmV0d2VlbiBlZHVjYXRpb25hbCBhdHRhaW5tZW50IChQQ1RCQUNITU9SKSBhbmQgaG91c2luZyB2YWx1ZXMgaGlnaGxpZ2h0cyB0aGUgaW1wb3J0YW5jZSBvZiBleHBhbmRpbmcgYWNjZXNzIHRvIGhpZ2gtcXVhbGl0eSBlZHVjYXRpb24gYW5kIHdvcmtmb3JjZSBkZXZlbG9wbWVudC4gSG93ZXZlciwgaW5jcmVhc2luZyBlZHVjYXRpb24gbGV2ZWxzIGFsb25lIGRvZXMgbm90IGVuc3VyZSBlcXVpdGFibGUgaG91c2luZyBvdXRjb21lcyBpZiBob3VzaW5nIGNvc3RzIHJpc2UgYmV5b25kIGFmZm9yZGFiaWxpdHkgZm9yIGV4aXN0aW5nIHJlc2lkZW50cy4gVGh1cywgcG9saWNpZXMgc2hvdWxkIGJlIGRlc2lnbmVkIHRvIGJhbGFuY2UgZWR1Y2F0aW9uYWwgaW52ZXN0bWVudCB3aXRoIGFmZm9yZGFiaWxpdHkgbWVhc3VyZXMsIHN1Y2ggYXMgcmVudGFsIGFzc2lzdGFuY2UgcHJvZ3JhbXMgYW5kIGZpcnN0LXRpbWUgaG9tZWJ1eWVyIHN1cHBvcnQgZm9yIGxvd2VyLWluY29tZSBob3VzZWhvbGRzLgoKVGhlIG5lZ2F0aXZlIGFzc29jaWF0aW9uIGJldHdlZW4gcG92ZXJ0eSBsZXZlbHMgKExOTkJFTFBPVjEwMCkgYW5kIGhvdXNpbmcgdmFsdWVzIGhpZ2hsaWdodHMgdGhlIG5lZWQgZm9yIGhvdXNpbmcgcG9saWNpZXMgdGhhdCBhY3RpdmVseSBjb21iYXQgZWNvbm9taWMgaW5lcXVhbGl0eSBhbmQgc3VwcG9ydCBhZmZvcmRhYmxlLCBzdGFibGUgY29tbXVuaXRpZXMuIFNvbHV0aW9ucyBzdWNoIGFzIG1peGVkLWluY29tZSBob3VzaW5nIGRldmVsb3BtZW50cywgaW5jb21lLWJhc2VkIHRheCBjcmVkaXRzLCBhbmQgZXhwYW5kZWQgdGVuYW50IHByb3RlY3Rpb25zIGNhbiBoZWxwIGVuc3VyZSB0aGF0IGVjb25vbWljIG1vYmlsaXR5IGRvZXMgbm90IGNvbWUgYXQgdGhlIGNvc3Qgb2YgZGlzcGxhY2VtZW50LiBUaGUgZ29hbCBzaG91bGQgYmUgdG8gY3JlYXRlIHN0YWJsZSwgbWl4ZWQtaW5jb21lIGNvbW11bml0aWVzIHdoZXJlIGVjb25vbWljIGdyb3d0aCBiZW5lZml0cyBib3RoIGN1cnJlbnQgcmVzaWRlbnRzIGFuZCBuZXcgYXJyaXZhbHMuCgoqKkxpbWl0YXRpb25zIGFuZCBGdXR1cmUgUmVzZWFyY2g6KioKCkFsdGhvdWdoIG91ciBtb2RlbCBwcm92aWRlcyBhIHN0cm9uZyB1bmRlcnN0YW5kaW5nIG9mIGhvdXNpbmcgbWFya2V0IGR5bmFtaWNzLCB0aGVyZSBhcmUgc2V2ZXJhbCBsaW1pdGF0aW9ucyB0aGF0IGZ1dHVyZSByZXNlYXJjaCBzaG91bGQgYWRkcmVzcy4gRmlyc3QsIHdoaWxlIG91ciBtb2RlbCBleHBsYWlucyBhIHNpZ25pZmljYW50IHBvcnRpb24gb2YgdGhlIHZhcmlhdGlvbiBpbiBob3VzaW5nIHZhbHVlcywgYWJvdXQgb25lLXRoaXJkIHJlbWFpbnMgdW5leHBsYWluZWQuIFRoaXMgc3VnZ2VzdHMgdGhhdCBvdGhlciBmYWN0b3JzIGxpa2UgYWNjZXNzIHRvIHRyYW5zcG9ydGF0aW9uLCBoaXN0b3JpY2FsIHJlZGxpbmluZyBwYXR0ZXJucywgb3IgdGhlIHByZXNlbmNlIG9mIHB1YmxpYyBhbWVuaXRpZXMgbWF5IHBsYXkgaW1wb3J0YW50IHJvbGVzIGFuZCBzaG91bGQgYmUgZXhwbG9yZWQgaW4gZnV0dXJlIHN0dWRpZXMuCgpUaGUgcG90ZW50aWFsIHByZXNlbmNlIG9mIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIHN1Z2dlc3RzIHRoYXQgbmVpZ2hib3JpbmcgYmxvY2sgZ3JvdXBzIG1heSBub3QgYmUgZW50aXJlbHkgaW5kZXBlbmRlbnQsIHdoaWNoIGNvdWxkIGJpYXMgc29tZSBlc3RpbWF0ZXMuIEluY29ycG9yYXRpbmcgc3BhdGlhbCBlY29ub21ldHJpYyB0ZWNobmlxdWVzLCBzdWNoIGFzIHNwYXRpYWwgbGFnIG1vZGVscyBvciBnZW9ncmFwaGljYWxseSB3ZWlnaHRlZCByZWdyZXNzaW9uLCBjb3VsZCBpbXByb3ZlIHRoZSBhY2N1cmFjeSBvZiBmdXR1cmUgYW5hbHlzZXMuCgojIyMgUG9zc2liaWxpdHkgb2YgUmlkZ2Ugb3IgTEFTU08gUmVncmVzc2lvbgoKUmlkZ2UgYW5kIExBU1NPIHJlZ3Jlc3Npb24gYXJlIHVzZWQgd2hlbiB0aGVyZSBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgcHJlZGljdG9ycyBvciB3aGVuIG9ubHkgYSBzdWJzZXQgb2YgZmVhdHVyZXMgaXMgZXhwZWN0ZWQgdG8gYmUgdHJ1bHkgaW1wb3J0YW50LiBJbiBzdWNoIGNhc2VzLCBzb21lIHByZWRpY3RvciBjb2VmZmljaWVudHMgbWF5IGJlY29tZSBleGNlc3NpdmVseSBsYXJnZSwgbGVhZGluZyB0byBvdmVyZml0dGluZyBpbiBhIGxpbmVhciBtb2RlbC4gVGhlc2UgbWV0aG9kcyBtYW5hZ2Ugb3ZlcmZpdHRpbmcgYnkgYWRkaW5nIGEgcGVuYWx0eSB0ZXJtIHRvIHRoZSBsb3NzIGZ1bmN0aW9uLCB3aGljaCBjb25zdHJhaW5zIHRoZSBjb2VmZmljaWVudHMuIEhvd2V2ZXIsIGluIG91ciBtb2RlbCwgdGhlIGhpZ2hlc3QgY29ycmVsYXRpb24gYmV0d2VlbiBwcmVkaWN0b3JzIGlzIDAuMzIsIGluZGljYXRpbmcgbm8gc2lnbmlmaWNhbnQgbXVsdGljb2xsaW5lYXJpdHkuIEFkZGl0aW9uYWxseSwgbm8gcHJlZGljdG9yIGV4aGliaXRzIGV4Y2Vzc2l2ZWx5IGxhcmdlIGNvZWZmaWNpZW50cy4gVGhlcmVmb3JlLCBhcHBseWluZyBSaWRnZSBvciBMQVNTTyByZWdyZXNzaW9uIGluIHRoaXMgY2FzZSB3b3VsZCBiZSB1bm5lY2Vzc2FyeS4=